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

     1  package application_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/kyma-incubator/compass/components/director/pkg/str"
    11  
    12  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
    13  	"github.com/kyma-incubator/compass/components/director/pkg/operation"
    14  
    15  	"github.com/kyma-incubator/compass/components/director/pkg/normalizer"
    16  
    17  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    18  
    19  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    20  	"github.com/sirupsen/logrus"
    21  
    22  	"github.com/google/uuid"
    23  	"github.com/kyma-incubator/compass/components/director/internal/domain/application"
    24  	"github.com/kyma-incubator/compass/components/director/internal/domain/application/automock"
    25  	"github.com/kyma-incubator/compass/components/director/internal/domain/tenant"
    26  	"github.com/kyma-incubator/compass/components/director/internal/labelfilter"
    27  	"github.com/kyma-incubator/compass/components/director/internal/model"
    28  	"github.com/kyma-incubator/compass/components/director/pkg/pagination"
    29  	"github.com/stretchr/testify/assert"
    30  	"github.com/stretchr/testify/mock"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  const testScenario = "test-scenario"
    35  
    36  func TestService_Create(t *testing.T) {
    37  	// GIVEN
    38  	timestamp := time.Now()
    39  	testErr := errors.New("Test error")
    40  	modelInput := applicationRegisterInputWithScenarios()
    41  
    42  	normalizedModelInput := model.ApplicationRegisterInput{
    43  		Name: "mp-foo-bar-not",
    44  		Webhooks: []*model.WebhookInput{
    45  			{URL: stringPtr("test.foo.com")},
    46  			{URL: stringPtr("test.bar.com")},
    47  		},
    48  
    49  		Labels: map[string]interface{}{
    50  			"label": "value",
    51  		},
    52  		IntegrationSystemID: &intSysID,
    53  	}
    54  	normalizedModelInput.Bundles = modelInput.Bundles
    55  
    56  	labels := map[string]interface{}{
    57  		"integrationSystemID":  intSysID,
    58  		"label":                "value",
    59  		"name":                 "mp-foo-bar-not",
    60  		"applicationType":      "test-app-with-ppms",
    61  		"ppmsProductVersionId": "1",
    62  	}
    63  	normalizedLabels := map[string]interface{}{
    64  		"integrationSystemID": intSysID,
    65  		"label":               "value",
    66  		"name":                "mp-foo-bar-not",
    67  	}
    68  	labelsWithoutIntSys := map[string]interface{}{
    69  		"integrationSystemID": "",
    70  		"name":                "mp-test",
    71  	}
    72  	labelsWithScenarios := map[string]interface{}{
    73  		"integrationSystemID": "",
    74  		"name":                "mp-test",
    75  		model.ScenariosKey:    []interface{}{testScenario},
    76  	}
    77  	var nilLabels map[string]interface{}
    78  
    79  	id := "foo"
    80  
    81  	tnt := "tenant"
    82  	externalTnt := "external-tnt"
    83  
    84  	appModel := modelFromInput(modelInput, tnt, id, applicationMatcher(modelInput.Name, modelInput.Description))
    85  	normalizedAppModel := modelFromInput(normalizedModelInput, tnt, id, applicationMatcher(normalizedModelInput.Name, normalizedModelInput.Description))
    86  
    87  	ctx := context.TODO()
    88  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
    89  
    90  	testCases := []struct {
    91  		Name               string
    92  		AppNameNormalizer  normalizer.Normalizator
    93  		AppRepoFn          func() *automock.ApplicationRepository
    94  		WebhookRepoFn      func() *automock.WebhookRepository
    95  		IntSysRepoFn       func() *automock.IntegrationSystemRepository
    96  		LabelServiceFn     func() *automock.LabelService
    97  		BundleServiceFn    func() *automock.BundleService
    98  		UIDServiceFn       func() *automock.UIDService
    99  		FormationServiceFn func() *automock.FormationService
   100  		Input              model.ApplicationRegisterInput
   101  		ExpectedErr        error
   102  	}{
   103  		{
   104  			Name:              "Success with scenarios label",
   105  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   106  			AppRepoFn: func() *automock.ApplicationRepository {
   107  				repo := &automock.ApplicationRepository{}
   108  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   109  				repo.On("Create", ctx, tnt, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return(nil).Once()
   110  				return repo
   111  			},
   112  			WebhookRepoFn: func() *automock.WebhookRepository {
   113  				repo := &automock.WebhookRepository{}
   114  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   115  				return repo
   116  			},
   117  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   118  				repo := &automock.IntegrationSystemRepository{}
   119  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   120  				return repo
   121  			},
   122  			LabelServiceFn: func() *automock.LabelService {
   123  				svc := &automock.LabelService{}
   124  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
   125  				return svc
   126  			},
   127  			BundleServiceFn: func() *automock.BundleService {
   128  				svc := &automock.BundleService{}
   129  				svc.On("CreateMultiple", ctx, resource.Application, id, modelInput.Bundles).Return(nil).Once()
   130  				return svc
   131  			},
   132  			UIDServiceFn: func() *automock.UIDService {
   133  				svc := &automock.UIDService{}
   134  				svc.On("Generate").Return(id)
   135  				return svc
   136  			},
   137  			FormationServiceFn: func() *automock.FormationService {
   138  				svc := &automock.FormationService{}
   139  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
   140  				return svc
   141  			},
   142  			Input:       applicationRegisterInputWithScenarios(),
   143  			ExpectedErr: nil,
   144  		},
   145  		{
   146  			Name:              "Returns success when listing existing applications returns empty applications",
   147  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   148  			AppRepoFn: func() *automock.ApplicationRepository {
   149  				repo := &automock.ApplicationRepository{}
   150  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{}, nil).Once()
   151  				repo.On("Create", ctx, tnt, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return(nil).Once()
   152  				return repo
   153  			},
   154  			WebhookRepoFn: func() *automock.WebhookRepository {
   155  				repo := &automock.WebhookRepository{}
   156  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   157  				return repo
   158  			},
   159  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   160  				repo := &automock.IntegrationSystemRepository{}
   161  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   162  				return repo
   163  			},
   164  			FormationServiceFn: func() *automock.FormationService {
   165  				svc := &automock.FormationService{}
   166  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
   167  				return svc
   168  			},
   169  			LabelServiceFn: func() *automock.LabelService {
   170  				svc := &automock.LabelService{}
   171  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
   172  				return svc
   173  			},
   174  			BundleServiceFn: func() *automock.BundleService {
   175  				svc := &automock.BundleService{}
   176  				svc.On("CreateMultiple", ctx, resource.Application, id, modelInput.Bundles).Return(nil).Once()
   177  				return svc
   178  			},
   179  			UIDServiceFn: func() *automock.UIDService {
   180  				svc := &automock.UIDService{}
   181  				svc.On("Generate").Return(id)
   182  				return svc
   183  			},
   184  			Input:       applicationRegisterInputWithScenarios(),
   185  			ExpectedErr: nil,
   186  		},
   187  		{
   188  			Name:              "Returns success when listing existing applications returns application with different name",
   189  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   190  			AppRepoFn: func() *automock.ApplicationRepository {
   191  				repo := &automock.ApplicationRepository{}
   192  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{{Name: modelInput.Name + "-test"}}, nil).Once()
   193  				repo.On("Create", ctx, tnt, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return(nil).Once()
   194  				return repo
   195  			},
   196  			WebhookRepoFn: func() *automock.WebhookRepository {
   197  				repo := &automock.WebhookRepository{}
   198  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   199  				return repo
   200  			},
   201  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   202  				repo := &automock.IntegrationSystemRepository{}
   203  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   204  				return repo
   205  			},
   206  			FormationServiceFn: func() *automock.FormationService {
   207  				svc := &automock.FormationService{}
   208  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
   209  				return svc
   210  			},
   211  			LabelServiceFn: func() *automock.LabelService {
   212  				svc := &automock.LabelService{}
   213  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
   214  				return svc
   215  			},
   216  			BundleServiceFn: func() *automock.BundleService {
   217  				svc := &automock.BundleService{}
   218  				svc.On("CreateMultiple", ctx, resource.Application, id, modelInput.Bundles).Return(nil).Once()
   219  				return svc
   220  			},
   221  			UIDServiceFn: func() *automock.UIDService {
   222  				svc := &automock.UIDService{}
   223  				svc.On("Generate").Return(id)
   224  				return svc
   225  			},
   226  			Input:       applicationRegisterInputWithScenarios(),
   227  			ExpectedErr: nil,
   228  		},
   229  		{
   230  			Name:              "Returns error when listing existing applications returns application with same name",
   231  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   232  			AppRepoFn: func() *automock.ApplicationRepository {
   233  				repo := &automock.ApplicationRepository{}
   234  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{{Name: modelInput.Name}}, nil).Once()
   235  				return repo
   236  			},
   237  			WebhookRepoFn:      UnusedWebhookRepository,
   238  			IntSysRepoFn:       UnusedIntegrationSystemRepository,
   239  			LabelServiceFn:     UnusedLabelService,
   240  			BundleServiceFn:    UnusedBundleService,
   241  			UIDServiceFn:       UnusedUIDService,
   242  			FormationServiceFn: UnusedFormationService,
   243  			Input:              applicationRegisterInputWithScenarios(),
   244  			ExpectedErr:        apperrors.NewNotUniqueNameError(resource.Application),
   245  		},
   246  		{
   247  			Name:              "Returns success when listing existing applications returns application with different name and incoming name is already normalized",
   248  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   249  			AppRepoFn: func() *automock.ApplicationRepository {
   250  				repo := &automock.ApplicationRepository{}
   251  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{{Name: normalizedModelInput.Name + "-test"}}, nil).Once()
   252  				repo.On("Create", ctx, tnt, mock.MatchedBy(normalizedAppModel.ApplicationMatcherFn)).Return(nil).Once()
   253  				return repo
   254  			},
   255  			WebhookRepoFn: func() *automock.WebhookRepository {
   256  				repo := &automock.WebhookRepository{}
   257  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   258  				return repo
   259  			},
   260  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   261  				repo := &automock.IntegrationSystemRepository{}
   262  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   263  				return repo
   264  			},
   265  			LabelServiceFn: func() *automock.LabelService {
   266  				svc := &automock.LabelService{}
   267  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, normalizedLabels).Return(nil).Once()
   268  				return svc
   269  			},
   270  			BundleServiceFn: func() *automock.BundleService {
   271  				svc := &automock.BundleService{}
   272  				svc.On("CreateMultiple", ctx, resource.Application, id, normalizedModelInput.Bundles).Return(nil).Once()
   273  				return svc
   274  			},
   275  			UIDServiceFn: func() *automock.UIDService {
   276  				svc := &automock.UIDService{}
   277  				svc.On("Generate").Return(id)
   278  				return svc
   279  			},
   280  			FormationServiceFn: UnusedFormationService,
   281  			Input:              normalizedModelInput,
   282  			ExpectedErr:        nil,
   283  		},
   284  		{
   285  			Name:              "Returns error when listing existing applications returns application with same name and incoming name is already normalized",
   286  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   287  			AppRepoFn: func() *automock.ApplicationRepository {
   288  				repo := &automock.ApplicationRepository{}
   289  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{{Name: normalizedModelInput.Name}}, nil).Once()
   290  				return repo
   291  			},
   292  			WebhookRepoFn:      UnusedWebhookRepository,
   293  			IntSysRepoFn:       UnusedIntegrationSystemRepository,
   294  			LabelServiceFn:     UnusedLabelService,
   295  			BundleServiceFn:    UnusedBundleService,
   296  			UIDServiceFn:       UnusedUIDService,
   297  			FormationServiceFn: UnusedFormationService,
   298  			Input:              normalizedModelInput,
   299  			ExpectedErr:        apperrors.NewNotUniqueNameError(resource.Application),
   300  		},
   301  		{
   302  			Name:              "Success when no labels provided",
   303  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   304  			AppRepoFn: func() *automock.ApplicationRepository {
   305  				repo := &automock.ApplicationRepository{}
   306  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   307  				repo.On("Create", ctx, tnt, mock.MatchedBy(applicationMatcher("test", nil))).Return(nil).Once()
   308  				return repo
   309  			},
   310  			WebhookRepoFn: func() *automock.WebhookRepository {
   311  				repo := &automock.WebhookRepository{}
   312  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   313  				return repo
   314  			},
   315  			IntSysRepoFn: UnusedIntegrationSystemRepository,
   316  			LabelServiceFn: func() *automock.LabelService {
   317  				svc := &automock.LabelService{}
   318  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labelsWithoutIntSys).Return(nil).Once()
   319  				return svc
   320  			},
   321  			BundleServiceFn: UnusedBundleService,
   322  			UIDServiceFn: func() *automock.UIDService {
   323  				svc := &automock.UIDService{}
   324  				svc.On("Generate").Return(id)
   325  				return svc
   326  			},
   327  			FormationServiceFn: UnusedFormationService,
   328  			Input:              model.ApplicationRegisterInput{Name: "test", Labels: nilLabels},
   329  			ExpectedErr:        nil,
   330  		},
   331  		{
   332  			Name:              "Success when scenarios label provided",
   333  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   334  			AppRepoFn: func() *automock.ApplicationRepository {
   335  				repo := &automock.ApplicationRepository{}
   336  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   337  				repo.On("Create", ctx, tnt, mock.MatchedBy(applicationMatcher("test", nil))).Return(nil).Once()
   338  				return repo
   339  			},
   340  			WebhookRepoFn: func() *automock.WebhookRepository {
   341  				repo := &automock.WebhookRepository{}
   342  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   343  				return repo
   344  			},
   345  			IntSysRepoFn:       UnusedIntegrationSystemRepository,
   346  			FormationServiceFn: UnusedFormationService,
   347  			LabelServiceFn: func() *automock.LabelService {
   348  				svc := &automock.LabelService{}
   349  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labelsWithoutIntSys).Return(nil).Once()
   350  				return svc
   351  			},
   352  			BundleServiceFn: UnusedBundleService,
   353  			UIDServiceFn: func() *automock.UIDService {
   354  				svc := &automock.UIDService{}
   355  				svc.On("Generate").Return(id)
   356  				return svc
   357  			},
   358  			Input: model.ApplicationRegisterInput{
   359  				Name:   "test",
   360  				Labels: labelsWithoutIntSys,
   361  			},
   362  			ExpectedErr: nil,
   363  		},
   364  		{
   365  			Name:              "Returns error when application creation failed",
   366  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   367  			AppRepoFn: func() *automock.ApplicationRepository {
   368  				repo := &automock.ApplicationRepository{}
   369  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   370  				repo.On("Create", ctx, tnt, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return(testErr).Once()
   371  				return repo
   372  			},
   373  			WebhookRepoFn: UnusedWebhookRepository,
   374  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   375  				repo := &automock.IntegrationSystemRepository{}
   376  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   377  				return repo
   378  			},
   379  			LabelServiceFn:  UnusedLabelService,
   380  			BundleServiceFn: UnusedBundleService,
   381  			UIDServiceFn: func() *automock.UIDService {
   382  				svc := &automock.UIDService{}
   383  				svc.On("Generate").Return(id).Once()
   384  				return svc
   385  			},
   386  			FormationServiceFn: UnusedFormationService,
   387  			Input:              applicationRegisterInputWithScenarios(),
   388  			ExpectedErr:        testErr,
   389  		},
   390  		{
   391  			Name:              "Returns error when listing existing applications fails",
   392  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   393  			AppRepoFn: func() *automock.ApplicationRepository {
   394  				repo := &automock.ApplicationRepository{}
   395  				repo.On("ListAll", ctx, mock.Anything).Return(nil, testErr).Once()
   396  				return repo
   397  			},
   398  			WebhookRepoFn:      UnusedWebhookRepository,
   399  			IntSysRepoFn:       UnusedIntegrationSystemRepository,
   400  			LabelServiceFn:     UnusedLabelService,
   401  			BundleServiceFn:    UnusedBundleService,
   402  			UIDServiceFn:       UnusedUIDService,
   403  			FormationServiceFn: UnusedFormationService,
   404  			Input:              applicationRegisterInputWithScenarios(),
   405  			ExpectedErr:        testErr,
   406  		},
   407  		{
   408  			Name:              "Returns error when integration system doesn't exist",
   409  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   410  			AppRepoFn: func() *automock.ApplicationRepository {
   411  				repo := &automock.ApplicationRepository{}
   412  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   413  				return repo
   414  			},
   415  			WebhookRepoFn: UnusedWebhookRepository,
   416  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   417  				repo := &automock.IntegrationSystemRepository{}
   418  				repo.On("Exists", ctx, intSysID).Return(false, nil).Once()
   419  				return repo
   420  			},
   421  			LabelServiceFn:     UnusedLabelService,
   422  			BundleServiceFn:    UnusedBundleService,
   423  			UIDServiceFn:       UnusedUIDService,
   424  			FormationServiceFn: UnusedFormationService,
   425  			Input:              applicationRegisterInputWithScenarios(),
   426  			ExpectedErr:        errors.New("Object not found"),
   427  		},
   428  		{
   429  			Name:              "Returns error when checking for integration system fails",
   430  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   431  			AppRepoFn: func() *automock.ApplicationRepository {
   432  				repo := &automock.ApplicationRepository{}
   433  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   434  				return repo
   435  			},
   436  			WebhookRepoFn: UnusedWebhookRepository,
   437  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   438  				repo := &automock.IntegrationSystemRepository{}
   439  				repo.On("Exists", ctx, intSysID).Return(false, testErr).Once()
   440  				return repo
   441  			},
   442  			LabelServiceFn:     UnusedLabelService,
   443  			BundleServiceFn:    UnusedBundleService,
   444  			UIDServiceFn:       UnusedUIDService,
   445  			FormationServiceFn: UnusedFormationService,
   446  			Input:              applicationRegisterInputWithScenarios(),
   447  			ExpectedErr:        testErr,
   448  		},
   449  		{
   450  			Name:              "Returns error when creating bundles",
   451  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   452  			AppRepoFn: func() *automock.ApplicationRepository {
   453  				repo := &automock.ApplicationRepository{}
   454  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   455  				repo.On("Create", ctx, tnt, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return(nil).Once()
   456  				return repo
   457  			},
   458  			WebhookRepoFn: func() *automock.WebhookRepository {
   459  				repo := &automock.WebhookRepository{}
   460  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   461  				return repo
   462  			},
   463  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   464  				repo := &automock.IntegrationSystemRepository{}
   465  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   466  				return repo
   467  			},
   468  			LabelServiceFn: func() *automock.LabelService {
   469  				svc := &automock.LabelService{}
   470  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
   471  				return svc
   472  			},
   473  			BundleServiceFn: func() *automock.BundleService {
   474  				svc := &automock.BundleService{}
   475  				svc.On("CreateMultiple", ctx, resource.Application, id, modelInput.Bundles).Return(testErr).Once()
   476  				return svc
   477  			},
   478  			UIDServiceFn: func() *automock.UIDService {
   479  				svc := &automock.UIDService{}
   480  				svc.On("Generate").Return(id)
   481  				return svc
   482  			},
   483  			FormationServiceFn: func() *automock.FormationService {
   484  				svc := &automock.FormationService{}
   485  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
   486  				return svc
   487  			},
   488  			Input:       applicationRegisterInputWithScenarios(),
   489  			ExpectedErr: testErr,
   490  		},
   491  		{
   492  			Name:              "Returns error when failing during assigning formation",
   493  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   494  			AppRepoFn: func() *automock.ApplicationRepository {
   495  				repo := &automock.ApplicationRepository{}
   496  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   497  				repo.On("Create", ctx, tnt, mock.MatchedBy(applicationMatcher("test", nil))).Return(nil).Once()
   498  				return repo
   499  			},
   500  			WebhookRepoFn: UnusedWebhookRepository,
   501  			IntSysRepoFn:  UnusedIntegrationSystemRepository,
   502  			LabelServiceFn: func() *automock.LabelService {
   503  				svc := &automock.LabelService{}
   504  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labelsWithScenarios).Return(nil).Once()
   505  				return svc
   506  			},
   507  			BundleServiceFn: UnusedBundleService,
   508  			UIDServiceFn: func() *automock.UIDService {
   509  				svc := &automock.UIDService{}
   510  				svc.On("Generate").Return(id)
   511  				return svc
   512  			},
   513  			FormationServiceFn: func() *automock.FormationService {
   514  				svc := &automock.FormationService{}
   515  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, testErr).Once()
   516  				return svc
   517  			},
   518  			Input:       model.ApplicationRegisterInput{Name: "test", Labels: labelsWithScenarios},
   519  			ExpectedErr: testErr,
   520  		},
   521  	}
   522  
   523  	for _, testCase := range testCases {
   524  		t.Run(testCase.Name, func(t *testing.T) {
   525  			appNameNormalizer := testCase.AppNameNormalizer
   526  			appRepo := testCase.AppRepoFn()
   527  			webhookRepo := testCase.WebhookRepoFn()
   528  			labelSvc := testCase.LabelServiceFn()
   529  			uidSvc := testCase.UIDServiceFn()
   530  			intSysRepo := testCase.IntSysRepoFn()
   531  			bndlSvc := testCase.BundleServiceFn()
   532  			formationSvc := testCase.FormationServiceFn()
   533  			svc := application.NewService(appNameNormalizer, nil, appRepo, webhookRepo, nil, nil, intSysRepo, labelSvc, bndlSvc, uidSvc, formationSvc, "", nil)
   534  			svc.SetTimestampGen(func() time.Time { return timestamp })
   535  
   536  			// WHEN
   537  			result, err := svc.Create(ctx, testCase.Input)
   538  
   539  			// THEN
   540  			assert.IsType(t, "string", result)
   541  			if testCase.ExpectedErr != nil {
   542  				require.NotNil(t, err)
   543  				assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
   544  			} else {
   545  				require.Nil(t, err)
   546  			}
   547  
   548  			mock.AssertExpectationsForObjects(t, appRepo, webhookRepo, labelSvc, uidSvc, intSysRepo, bndlSvc, formationSvc)
   549  		})
   550  	}
   551  
   552  	t.Run("Returns error on loading tenant", func(t *testing.T) {
   553  		svc := application.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
   554  		// WHEN
   555  		_, err := svc.Create(context.TODO(), model.ApplicationRegisterInput{})
   556  		assert.True(t, apperrors.IsCannotReadTenant(err))
   557  	})
   558  }
   559  
   560  func TestService_CreateFromTemplate(t *testing.T) {
   561  	// GIVEN
   562  	timestamp := time.Now()
   563  	testErr := errors.New("Test error")
   564  	modelInput := applicationRegisterInputWithScenarios()
   565  
   566  	normalizedModelInput := model.ApplicationRegisterInput{
   567  		Name: "mp-foo-bar-not",
   568  		Webhooks: []*model.WebhookInput{
   569  			{URL: stringPtr("test.foo.com")},
   570  			{URL: stringPtr("test.bar.com")},
   571  		},
   572  
   573  		Labels: map[string]interface{}{
   574  			"label": "value",
   575  		},
   576  		IntegrationSystemID: &intSysID,
   577  	}
   578  	normalizedModelInput.Bundles = modelInput.Bundles
   579  
   580  	labels := map[string]interface{}{
   581  		"integrationSystemID":  intSysID,
   582  		"label":                "value",
   583  		"name":                 "mp-foo-bar-not",
   584  		"applicationType":      "test-app-with-ppms",
   585  		"ppmsProductVersionId": "1",
   586  	}
   587  	normalizedLabels := map[string]interface{}{
   588  		"integrationSystemID": intSysID,
   589  		"label":               "value",
   590  		"name":                "mp-foo-bar-not",
   591  	}
   592  	labelsWithoutIntSys := map[string]interface{}{
   593  		"integrationSystemID": "",
   594  		"name":                "mp-test",
   595  	}
   596  	var nilLabels map[string]interface{}
   597  
   598  	id := "foo"
   599  	appTemplteID := "test-app-template"
   600  	tnt := "tenant"
   601  	externalTnt := "external-tnt"
   602  
   603  	appFromTemplateModel := modelFromInput(modelInput, tnt, id, applicationFromTemplateMatcher(modelInput.Name, modelInput.Description, &appTemplteID))
   604  	normalizedAppModel := modelFromInput(normalizedModelInput, tnt, id, applicationFromTemplateMatcher(normalizedModelInput.Name, normalizedModelInput.Description, &appTemplteID))
   605  
   606  	ctx := context.TODO()
   607  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
   608  
   609  	testCases := []struct {
   610  		Name               string
   611  		AppNameNormalizer  normalizer.Normalizator
   612  		AppRepoFn          func() *automock.ApplicationRepository
   613  		WebhookRepoFn      func() *automock.WebhookRepository
   614  		IntSysRepoFn       func() *automock.IntegrationSystemRepository
   615  		LabelServiceFn     func() *automock.LabelService
   616  		BundleServiceFn    func() *automock.BundleService
   617  		UIDServiceFn       func() *automock.UIDService
   618  		FormationServiceFn func() *automock.FormationService
   619  		Input              model.ApplicationRegisterInput
   620  		ExpectedErr        error
   621  	}{
   622  		{
   623  			Name:              "Success",
   624  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   625  			AppRepoFn: func() *automock.ApplicationRepository {
   626  				repo := &automock.ApplicationRepository{}
   627  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   628  				repo.On("Create", ctx, tnt, mock.MatchedBy(appFromTemplateModel.ApplicationMatcherFn)).Return(nil).Once()
   629  				return repo
   630  			},
   631  			WebhookRepoFn: func() *automock.WebhookRepository {
   632  				repo := &automock.WebhookRepository{}
   633  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   634  				return repo
   635  			},
   636  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   637  				repo := &automock.IntegrationSystemRepository{}
   638  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   639  				return repo
   640  			},
   641  			LabelServiceFn: func() *automock.LabelService {
   642  				svc := &automock.LabelService{}
   643  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
   644  				return svc
   645  			},
   646  			BundleServiceFn: func() *automock.BundleService {
   647  				svc := &automock.BundleService{}
   648  				svc.On("CreateMultiple", ctx, resource.Application, id, modelInput.Bundles).Return(nil).Once()
   649  				return svc
   650  			},
   651  			UIDServiceFn: func() *automock.UIDService {
   652  				svc := &automock.UIDService{}
   653  				svc.On("Generate").Return(id)
   654  				return svc
   655  			},
   656  			FormationServiceFn: func() *automock.FormationService {
   657  				svc := &automock.FormationService{}
   658  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
   659  				return svc
   660  			},
   661  			Input:       applicationRegisterInputWithScenarios(),
   662  			ExpectedErr: nil,
   663  		},
   664  		{
   665  			Name:              "Returns success when listing existing applications returns empty applications",
   666  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   667  			AppRepoFn: func() *automock.ApplicationRepository {
   668  				repo := &automock.ApplicationRepository{}
   669  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{}, nil).Once()
   670  				repo.On("Create", ctx, tnt, mock.MatchedBy(appFromTemplateModel.ApplicationMatcherFn)).Return(nil).Once()
   671  				return repo
   672  			},
   673  			WebhookRepoFn: func() *automock.WebhookRepository {
   674  				repo := &automock.WebhookRepository{}
   675  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   676  				return repo
   677  			},
   678  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   679  				repo := &automock.IntegrationSystemRepository{}
   680  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   681  				return repo
   682  			},
   683  			LabelServiceFn: func() *automock.LabelService {
   684  				svc := &automock.LabelService{}
   685  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
   686  				return svc
   687  			},
   688  			BundleServiceFn: func() *automock.BundleService {
   689  				svc := &automock.BundleService{}
   690  				svc.On("CreateMultiple", ctx, resource.Application, id, modelInput.Bundles).Return(nil).Once()
   691  				return svc
   692  			},
   693  			UIDServiceFn: func() *automock.UIDService {
   694  				svc := &automock.UIDService{}
   695  				svc.On("Generate").Return(id)
   696  				return svc
   697  			},
   698  			FormationServiceFn: func() *automock.FormationService {
   699  				svc := &automock.FormationService{}
   700  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
   701  				return svc
   702  			},
   703  			Input:       applicationRegisterInputWithScenarios(),
   704  			ExpectedErr: nil,
   705  		},
   706  		{
   707  			Name:              "Returns success when listing existing applications returns application with different name",
   708  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   709  			AppRepoFn: func() *automock.ApplicationRepository {
   710  				repo := &automock.ApplicationRepository{}
   711  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{{Name: modelInput.Name + "-test"}}, nil).Once()
   712  				repo.On("Create", ctx, tnt, mock.MatchedBy(appFromTemplateModel.ApplicationMatcherFn)).Return(nil).Once()
   713  				return repo
   714  			},
   715  			WebhookRepoFn: func() *automock.WebhookRepository {
   716  				repo := &automock.WebhookRepository{}
   717  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   718  				return repo
   719  			},
   720  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   721  				repo := &automock.IntegrationSystemRepository{}
   722  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   723  				return repo
   724  			},
   725  			LabelServiceFn: func() *automock.LabelService {
   726  				svc := &automock.LabelService{}
   727  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
   728  				return svc
   729  			},
   730  			BundleServiceFn: func() *automock.BundleService {
   731  				svc := &automock.BundleService{}
   732  				svc.On("CreateMultiple", ctx, resource.Application, id, modelInput.Bundles).Return(nil).Once()
   733  				return svc
   734  			},
   735  			UIDServiceFn: func() *automock.UIDService {
   736  				svc := &automock.UIDService{}
   737  				svc.On("Generate").Return(id)
   738  				return svc
   739  			},
   740  			FormationServiceFn: func() *automock.FormationService {
   741  				svc := &automock.FormationService{}
   742  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
   743  				return svc
   744  			},
   745  			Input:       applicationRegisterInputWithScenarios(),
   746  			ExpectedErr: nil,
   747  		},
   748  		{
   749  			Name:              "Returns error when listing existing applications returns application with same name",
   750  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   751  			AppRepoFn: func() *automock.ApplicationRepository {
   752  				repo := &automock.ApplicationRepository{}
   753  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{{Name: modelInput.Name}}, nil).Once()
   754  				return repo
   755  			},
   756  			WebhookRepoFn:      UnusedWebhookRepository,
   757  			IntSysRepoFn:       UnusedIntegrationSystemRepository,
   758  			LabelServiceFn:     UnusedLabelService,
   759  			BundleServiceFn:    UnusedBundleService,
   760  			UIDServiceFn:       UnusedUIDService,
   761  			FormationServiceFn: UnusedFormationService,
   762  			Input:              applicationRegisterInputWithScenarios(),
   763  			ExpectedErr:        apperrors.NewNotUniqueNameError(resource.Application),
   764  		},
   765  		{
   766  			Name:              "Returns success when listing existing applications returns application with different name and incoming name is already normalized",
   767  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   768  			AppRepoFn: func() *automock.ApplicationRepository {
   769  				repo := &automock.ApplicationRepository{}
   770  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{{Name: normalizedModelInput.Name + "-test"}}, nil).Once()
   771  				repo.On("Create", ctx, tnt, mock.MatchedBy(normalizedAppModel.ApplicationMatcherFn)).Return(nil).Once()
   772  				return repo
   773  			},
   774  			WebhookRepoFn: func() *automock.WebhookRepository {
   775  				repo := &automock.WebhookRepository{}
   776  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   777  				return repo
   778  			},
   779  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   780  				repo := &automock.IntegrationSystemRepository{}
   781  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   782  				return repo
   783  			},
   784  			LabelServiceFn: func() *automock.LabelService {
   785  				svc := &automock.LabelService{}
   786  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, normalizedLabels).Return(nil).Once()
   787  				return svc
   788  			},
   789  			BundleServiceFn: func() *automock.BundleService {
   790  				svc := &automock.BundleService{}
   791  				svc.On("CreateMultiple", ctx, resource.Application, id, normalizedModelInput.Bundles).Return(nil).Once()
   792  				return svc
   793  			},
   794  			UIDServiceFn: func() *automock.UIDService {
   795  				svc := &automock.UIDService{}
   796  				svc.On("Generate").Return(id)
   797  				return svc
   798  			},
   799  			FormationServiceFn: UnusedFormationService,
   800  			Input:              normalizedModelInput,
   801  			ExpectedErr:        nil,
   802  		},
   803  		{
   804  			Name:              "Returns error when listing existing applications returns application with same name and incoming name is already normalized",
   805  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   806  			AppRepoFn: func() *automock.ApplicationRepository {
   807  				repo := &automock.ApplicationRepository{}
   808  				repo.On("ListAll", ctx, mock.Anything).Return([]*model.Application{{Name: normalizedModelInput.Name}}, nil).Once()
   809  				return repo
   810  			},
   811  			WebhookRepoFn:      UnusedWebhookRepository,
   812  			IntSysRepoFn:       UnusedIntegrationSystemRepository,
   813  			LabelServiceFn:     UnusedLabelService,
   814  			BundleServiceFn:    UnusedBundleService,
   815  			UIDServiceFn:       UnusedUIDService,
   816  			FormationServiceFn: UnusedFormationService,
   817  			Input:              normalizedModelInput,
   818  			ExpectedErr:        apperrors.NewNotUniqueNameError(resource.Application),
   819  		},
   820  		{
   821  			Name:              "Success when no labels provided",
   822  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   823  			AppRepoFn: func() *automock.ApplicationRepository {
   824  				repo := &automock.ApplicationRepository{}
   825  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   826  				repo.On("Create", ctx, tnt, mock.MatchedBy(applicationMatcher("test", nil))).Return(nil).Once()
   827  				return repo
   828  			},
   829  			WebhookRepoFn: func() *automock.WebhookRepository {
   830  				repo := &automock.WebhookRepository{}
   831  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   832  				return repo
   833  			},
   834  			IntSysRepoFn: UnusedIntegrationSystemRepository,
   835  			LabelServiceFn: func() *automock.LabelService {
   836  				svc := &automock.LabelService{}
   837  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labelsWithoutIntSys).Return(nil).Once()
   838  				return svc
   839  			},
   840  			BundleServiceFn: UnusedBundleService,
   841  			UIDServiceFn: func() *automock.UIDService {
   842  				svc := &automock.UIDService{}
   843  				svc.On("Generate").Return(id)
   844  				return svc
   845  			},
   846  			FormationServiceFn: UnusedFormationService,
   847  			Input:              model.ApplicationRegisterInput{Name: "test", Labels: nilLabels},
   848  			ExpectedErr:        nil,
   849  		},
   850  		{
   851  			Name:              "Returns error when application creation failed",
   852  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   853  			AppRepoFn: func() *automock.ApplicationRepository {
   854  				repo := &automock.ApplicationRepository{}
   855  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   856  				repo.On("Create", ctx, tnt, mock.MatchedBy(appFromTemplateModel.ApplicationMatcherFn)).Return(testErr).Once()
   857  				return repo
   858  			},
   859  			WebhookRepoFn: UnusedWebhookRepository,
   860  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   861  				repo := &automock.IntegrationSystemRepository{}
   862  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   863  				return repo
   864  			},
   865  			LabelServiceFn:  UnusedLabelService,
   866  			BundleServiceFn: UnusedBundleService,
   867  			UIDServiceFn: func() *automock.UIDService {
   868  				svc := &automock.UIDService{}
   869  				svc.On("Generate").Return(id).Once()
   870  				return svc
   871  			},
   872  			FormationServiceFn: UnusedFormationService,
   873  			Input:              applicationRegisterInputWithScenarios(),
   874  			ExpectedErr:        testErr,
   875  		},
   876  		{
   877  			Name:              "Returns error when listing existing applications fails",
   878  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   879  			AppRepoFn: func() *automock.ApplicationRepository {
   880  				repo := &automock.ApplicationRepository{}
   881  				repo.On("ListAll", ctx, mock.Anything).Return(nil, testErr).Once()
   882  				return repo
   883  			},
   884  			WebhookRepoFn:      UnusedWebhookRepository,
   885  			IntSysRepoFn:       UnusedIntegrationSystemRepository,
   886  			LabelServiceFn:     UnusedLabelService,
   887  			BundleServiceFn:    UnusedBundleService,
   888  			UIDServiceFn:       UnusedUIDService,
   889  			FormationServiceFn: UnusedFormationService,
   890  			Input:              applicationRegisterInputWithScenarios(),
   891  			ExpectedErr:        testErr,
   892  		},
   893  		{
   894  			Name:              "Returns error when integration system doesn't exist",
   895  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   896  			AppRepoFn: func() *automock.ApplicationRepository {
   897  				repo := &automock.ApplicationRepository{}
   898  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   899  				return repo
   900  			},
   901  			WebhookRepoFn: UnusedWebhookRepository,
   902  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   903  				repo := &automock.IntegrationSystemRepository{}
   904  				repo.On("Exists", ctx, intSysID).Return(false, nil).Once()
   905  				return repo
   906  			},
   907  			LabelServiceFn:     UnusedLabelService,
   908  			BundleServiceFn:    UnusedBundleService,
   909  			UIDServiceFn:       UnusedUIDService,
   910  			FormationServiceFn: UnusedFormationService,
   911  			Input:              applicationRegisterInputWithScenarios(),
   912  			ExpectedErr:        errors.New("Object not found"),
   913  		},
   914  		{
   915  			Name:              "Returns error when checking for integration system fails",
   916  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   917  			AppRepoFn: func() *automock.ApplicationRepository {
   918  				repo := &automock.ApplicationRepository{}
   919  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   920  				return repo
   921  			},
   922  			WebhookRepoFn: UnusedWebhookRepository,
   923  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   924  				repo := &automock.IntegrationSystemRepository{}
   925  				repo.On("Exists", ctx, intSysID).Return(false, testErr).Once()
   926  				return repo
   927  			},
   928  			LabelServiceFn:     UnusedLabelService,
   929  			BundleServiceFn:    UnusedBundleService,
   930  			UIDServiceFn:       UnusedUIDService,
   931  			FormationServiceFn: UnusedFormationService,
   932  			Input:              applicationRegisterInputWithScenarios(),
   933  			ExpectedErr:        testErr,
   934  		},
   935  		{
   936  			Name:              "Returns error when creating bundles",
   937  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
   938  			AppRepoFn: func() *automock.ApplicationRepository {
   939  				repo := &automock.ApplicationRepository{}
   940  				repo.On("ListAll", ctx, mock.Anything).Return(nil, nil).Once()
   941  				repo.On("Create", ctx, tnt, mock.MatchedBy(appFromTemplateModel.ApplicationMatcherFn)).Return(nil).Once()
   942  				return repo
   943  			},
   944  			WebhookRepoFn: func() *automock.WebhookRepository {
   945  				repo := &automock.WebhookRepository{}
   946  				repo.On("CreateMany", ctx, tnt, mock.Anything).Return(nil).Once()
   947  				return repo
   948  			},
   949  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
   950  				repo := &automock.IntegrationSystemRepository{}
   951  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
   952  				return repo
   953  			},
   954  			LabelServiceFn: func() *automock.LabelService {
   955  				svc := &automock.LabelService{}
   956  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
   957  				return svc
   958  			},
   959  			BundleServiceFn: func() *automock.BundleService {
   960  				svc := &automock.BundleService{}
   961  				svc.On("CreateMultiple", ctx, resource.Application, id, modelInput.Bundles).Return(testErr).Once()
   962  				return svc
   963  			},
   964  			UIDServiceFn: func() *automock.UIDService {
   965  				svc := &automock.UIDService{}
   966  				svc.On("Generate").Return(id)
   967  				return svc
   968  			},
   969  			FormationServiceFn: func() *automock.FormationService {
   970  				svc := &automock.FormationService{}
   971  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
   972  				return svc
   973  			},
   974  			Input:       applicationRegisterInputWithScenarios(),
   975  			ExpectedErr: testErr,
   976  		},
   977  	}
   978  
   979  	for _, testCase := range testCases {
   980  		t.Run(testCase.Name, func(t *testing.T) {
   981  			appNameNormalizer := testCase.AppNameNormalizer
   982  			appRepo := testCase.AppRepoFn()
   983  			webhookRepo := testCase.WebhookRepoFn()
   984  			labelSvc := testCase.LabelServiceFn()
   985  			uidSvc := testCase.UIDServiceFn()
   986  			intSysRepo := testCase.IntSysRepoFn()
   987  			bndlSvc := testCase.BundleServiceFn()
   988  			formationSvc := testCase.FormationServiceFn()
   989  			svc := application.NewService(appNameNormalizer, nil, appRepo, webhookRepo, nil, nil, intSysRepo, labelSvc, bndlSvc, uidSvc, formationSvc, "", nil)
   990  			svc.SetTimestampGen(func() time.Time { return timestamp })
   991  
   992  			// WHEN
   993  			result, err := svc.CreateFromTemplate(ctx, testCase.Input, &appTemplteID)
   994  
   995  			// then
   996  			assert.IsType(t, "string", result)
   997  			if testCase.ExpectedErr != nil {
   998  				require.NotNil(t, err)
   999  				assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
  1000  			} else {
  1001  				require.Nil(t, err)
  1002  			}
  1003  
  1004  			mock.AssertExpectationsForObjects(t, appRepo, intSysRepo, uidSvc, bndlSvc, formationSvc, webhookRepo, labelSvc)
  1005  		})
  1006  	}
  1007  
  1008  	t.Run("Returns error on loading tenant", func(t *testing.T) {
  1009  		svc := application.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  1010  		// WHEN
  1011  		_, err := svc.Create(context.TODO(), model.ApplicationRegisterInput{})
  1012  		assert.True(t, apperrors.IsCannotReadTenant(err))
  1013  	})
  1014  }
  1015  
  1016  func TestService_Upsert_TrustedUpsert(t *testing.T) {
  1017  	// given
  1018  	timestamp := time.Now()
  1019  	testErr := errors.New("Test error")
  1020  	modelInput := applicationRegisterInputWithScenarios()
  1021  
  1022  	normalizedModelInput := model.ApplicationRegisterInput{
  1023  		Name: "mp-foo-bar-not",
  1024  		Webhooks: []*model.WebhookInput{
  1025  			{URL: stringPtr("test.foo.com")},
  1026  			{URL: stringPtr("test.bar.com")},
  1027  		},
  1028  
  1029  		Labels: map[string]interface{}{
  1030  			"label": "value",
  1031  		},
  1032  		IntegrationSystemID: &intSysID,
  1033  	}
  1034  	normalizedModelInput.Bundles = modelInput.Bundles
  1035  
  1036  	labels := map[string]interface{}{
  1037  		"integrationSystemID":  intSysID,
  1038  		"label":                "value",
  1039  		"name":                 "mp-foo-bar-not",
  1040  		"applicationType":      "test-app-with-ppms",
  1041  		"ppmsProductVersionId": "1",
  1042  	}
  1043  
  1044  	labelsWithoutIntSys := map[string]interface{}{
  1045  		"integrationSystemID": "",
  1046  		"name":                "mp-test",
  1047  	}
  1048  
  1049  	labelsWithInvalidPpmsProductVersion := map[string]interface{}{
  1050  		"integrationSystemID":  intSysID,
  1051  		"label":                "value",
  1052  		"name":                 "mp-foo-bar-not",
  1053  		"applicationType":      "test-app-with-ppms",
  1054  		"ppmsProductVersionId": "2",
  1055  	}
  1056  
  1057  	var nilLabels map[string]interface{}
  1058  
  1059  	modelInputWithoutApplicationType := model.ApplicationRegisterInput{
  1060  		Name: "foo.bar-not",
  1061  		Labels: map[string]interface{}{
  1062  			"label":                "value",
  1063  			"ppmsProductVersionId": "1",
  1064  		},
  1065  		IntegrationSystemID: &intSysID,
  1066  		BaseURL:             str.Ptr("http://test.com"),
  1067  	}
  1068  
  1069  	id := "foo"
  1070  
  1071  	tnt := "tenant"
  1072  	externalTnt := "external-tnt"
  1073  
  1074  	appModel := modelFromInput(modelInput, tnt, id, applicationMatcher(modelInput.Name, modelInput.Description))
  1075  
  1076  	ctx := context.TODO()
  1077  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  1078  
  1079  	ordWebhookMapping := []application.ORDWebhookMapping{
  1080  		{
  1081  			Type: "test-app",
  1082  		},
  1083  		{
  1084  			Type:                "test-app-with-ppms",
  1085  			PpmsProductVersions: []string{"1"},
  1086  		},
  1087  	}
  1088  
  1089  	testCases := []struct {
  1090  		Name               string
  1091  		AppNameNormalizer  normalizer.Normalizator
  1092  		AppRepoFn          func(string) *automock.ApplicationRepository
  1093  		IntSysRepoFn       func() *automock.IntegrationSystemRepository
  1094  		LabelServiceFn     func() *automock.LabelService
  1095  		LabelRepoFn        func() *automock.LabelRepository
  1096  		UIDServiceFn       func() *automock.UIDService
  1097  		WebhookRepoFn      func() *automock.WebhookRepository
  1098  		FormationServiceFn func() *automock.FormationService
  1099  		GetInput           func() model.ApplicationRegisterInput
  1100  		OrdWebhookMapping  []application.ORDWebhookMapping
  1101  		ExpectedErr        error
  1102  	}{
  1103  		{
  1104  			Name:              "Success",
  1105  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1106  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1107  				repo := &automock.ApplicationRepository{}
  1108  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1109  				return repo
  1110  			},
  1111  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1112  				repo := &automock.IntegrationSystemRepository{}
  1113  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1114  				return repo
  1115  			},
  1116  			LabelServiceFn: func() *automock.LabelService {
  1117  				svc := &automock.LabelService{}
  1118  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
  1119  				return svc
  1120  			},
  1121  			LabelRepoFn: func() *automock.LabelRepository {
  1122  				repo := &automock.LabelRepository{}
  1123  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.ApplicationLabel, "")).Once()
  1124  				return repo
  1125  			},
  1126  			UIDServiceFn: func() *automock.UIDService {
  1127  				svc := &automock.UIDService{}
  1128  				svc.On("Generate").Return(id)
  1129  				return svc
  1130  			},
  1131  			WebhookRepoFn: func() *automock.WebhookRepository {
  1132  				webhookRepo := &automock.WebhookRepository{}
  1133  				wh := &model.Webhook{
  1134  					URL:      stringPtr("test.foo.com"),
  1135  					ObjectID: id,
  1136  				}
  1137  				webhookRepo.On("ListByReferenceObjectID", ctx, tnt, id, model.ApplicationWebhookReference).Return([]*model.Webhook{wh}, nil)
  1138  				webhookRepo.On("CreateMany", ctx, tnt, mock.AnythingOfType("[]*model.Webhook")).Return(nil)
  1139  				return webhookRepo
  1140  			},
  1141  			FormationServiceFn: func() *automock.FormationService {
  1142  				svc := &automock.FormationService{}
  1143  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1144  				return svc
  1145  			},
  1146  			OrdWebhookMapping: ordWebhookMapping,
  1147  			GetInput: func() model.ApplicationRegisterInput {
  1148  				return applicationRegisterInputWithScenarios()
  1149  			},
  1150  			ExpectedErr: nil,
  1151  		},
  1152  		{
  1153  			Name:              "Success when no labels provided",
  1154  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1155  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1156  				repo := &automock.ApplicationRepository{}
  1157  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(applicationMatcher("test", nil))).Return("foo", nil).Once()
  1158  				return repo
  1159  			},
  1160  			IntSysRepoFn: UnusedIntegrationSystemRepository,
  1161  			LabelServiceFn: func() *automock.LabelService {
  1162  				svc := &automock.LabelService{}
  1163  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labelsWithoutIntSys).Return(nil).Once()
  1164  				return svc
  1165  			},
  1166  			LabelRepoFn: UnusedLabelRepository,
  1167  			UIDServiceFn: func() *automock.UIDService {
  1168  				svc := &automock.UIDService{}
  1169  				svc.On("Generate").Return(id)
  1170  				return svc
  1171  			},
  1172  			WebhookRepoFn:      UnusedWebhookRepository,
  1173  			FormationServiceFn: UnusedFormationService,
  1174  			GetInput: func() model.ApplicationRegisterInput {
  1175  				return model.ApplicationRegisterInput{Name: "test", Labels: nilLabels}
  1176  			},
  1177  			ExpectedErr: nil,
  1178  		},
  1179  		{
  1180  			Name:              "Success when scenarios label not provided",
  1181  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1182  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1183  				repo := &automock.ApplicationRepository{}
  1184  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(applicationMatcher("test", nil))).Return("foo", nil).Once()
  1185  				return repo
  1186  			},
  1187  			IntSysRepoFn: UnusedIntegrationSystemRepository,
  1188  			LabelServiceFn: func() *automock.LabelService {
  1189  				svc := &automock.LabelService{}
  1190  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labelsWithoutIntSys).Return(nil).Once()
  1191  				return svc
  1192  			},
  1193  			LabelRepoFn: UnusedLabelRepository,
  1194  			UIDServiceFn: func() *automock.UIDService {
  1195  				svc := &automock.UIDService{}
  1196  				svc.On("Generate").Return(id)
  1197  				return svc
  1198  			},
  1199  			WebhookRepoFn:      UnusedWebhookRepository,
  1200  			FormationServiceFn: UnusedFormationService,
  1201  			GetInput: func() model.ApplicationRegisterInput {
  1202  				return model.ApplicationRegisterInput{
  1203  					Name:   "test",
  1204  					Labels: labelsWithoutIntSys,
  1205  				}
  1206  			},
  1207  			ExpectedErr: nil,
  1208  		},
  1209  		{
  1210  			Name:              "Error when assigning formation",
  1211  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1212  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1213  				repo := &automock.ApplicationRepository{}
  1214  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1215  				return repo
  1216  			},
  1217  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1218  				repo := &automock.IntegrationSystemRepository{}
  1219  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1220  				return repo
  1221  			},
  1222  			LabelServiceFn: UnusedLabelService,
  1223  			LabelRepoFn: func() *automock.LabelRepository {
  1224  				repo := &automock.LabelRepository{}
  1225  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.ApplicationLabel, "")).Once()
  1226  				return repo
  1227  			},
  1228  			UIDServiceFn: func() *automock.UIDService {
  1229  				svc := &automock.UIDService{}
  1230  				svc.On("Generate").Return(id)
  1231  				return svc
  1232  			},
  1233  			WebhookRepoFn: UnusedWebhookRepository,
  1234  			FormationServiceFn: func() *automock.FormationService {
  1235  				svc := &automock.FormationService{}
  1236  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, testErr).Once()
  1237  				return svc
  1238  			},
  1239  			OrdWebhookMapping: ordWebhookMapping,
  1240  			GetInput: func() model.ApplicationRegisterInput {
  1241  				return applicationRegisterInputWithScenarios()
  1242  			},
  1243  			ExpectedErr: testErr,
  1244  		},
  1245  		{
  1246  			Name:              "Returns error when listing webhooks",
  1247  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1248  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1249  				repo := &automock.ApplicationRepository{}
  1250  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1251  				return repo
  1252  			},
  1253  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1254  				repo := &automock.IntegrationSystemRepository{}
  1255  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1256  				return repo
  1257  			},
  1258  			LabelServiceFn: func() *automock.LabelService {
  1259  				svc := &automock.LabelService{}
  1260  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
  1261  				return svc
  1262  			},
  1263  			LabelRepoFn: func() *automock.LabelRepository {
  1264  				repo := &automock.LabelRepository{}
  1265  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.ApplicationLabel, "")).Once()
  1266  				return repo
  1267  			},
  1268  			UIDServiceFn: func() *automock.UIDService {
  1269  				svc := &automock.UIDService{}
  1270  				svc.On("Generate").Return(id)
  1271  				return svc
  1272  			},
  1273  			WebhookRepoFn: func() *automock.WebhookRepository {
  1274  				webhookRepo := &automock.WebhookRepository{}
  1275  				webhookRepo.On("ListByReferenceObjectID", ctx, tnt, id, model.ApplicationWebhookReference).Return(nil, testErr)
  1276  				return webhookRepo
  1277  			},
  1278  			FormationServiceFn: func() *automock.FormationService {
  1279  				svc := &automock.FormationService{}
  1280  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1281  				return svc
  1282  			},
  1283  			OrdWebhookMapping: ordWebhookMapping,
  1284  			GetInput: func() model.ApplicationRegisterInput {
  1285  				return applicationRegisterInputWithScenarios()
  1286  			},
  1287  			ExpectedErr: testErr,
  1288  		},
  1289  		{
  1290  			Name:              "Returns error when creating webhooks",
  1291  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1292  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1293  				repo := &automock.ApplicationRepository{}
  1294  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1295  				return repo
  1296  			},
  1297  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1298  				repo := &automock.IntegrationSystemRepository{}
  1299  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1300  				return repo
  1301  			},
  1302  			LabelServiceFn: func() *automock.LabelService {
  1303  				svc := &automock.LabelService{}
  1304  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
  1305  				return svc
  1306  			},
  1307  			LabelRepoFn: func() *automock.LabelRepository {
  1308  				repo := &automock.LabelRepository{}
  1309  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.ApplicationLabel, "")).Once()
  1310  				return repo
  1311  			},
  1312  			UIDServiceFn: func() *automock.UIDService {
  1313  				svc := &automock.UIDService{}
  1314  				svc.On("Generate").Return(id)
  1315  				return svc
  1316  			},
  1317  			WebhookRepoFn: func() *automock.WebhookRepository {
  1318  				webhookRepo := &automock.WebhookRepository{}
  1319  				webhookRepo.On("ListByReferenceObjectID", ctx, tnt, id, model.ApplicationWebhookReference).Return([]*model.Webhook{}, nil)
  1320  				webhookRepo.On("CreateMany", ctx, tnt, mock.AnythingOfType("[]*model.Webhook")).Return(testErr)
  1321  				return webhookRepo
  1322  			},
  1323  			FormationServiceFn: func() *automock.FormationService {
  1324  				svc := &automock.FormationService{}
  1325  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1326  				return svc
  1327  			},
  1328  			OrdWebhookMapping: ordWebhookMapping,
  1329  			GetInput: func() model.ApplicationRegisterInput {
  1330  				return applicationRegisterInputWithScenarios()
  1331  			},
  1332  			ExpectedErr: testErr,
  1333  		},
  1334  		{
  1335  			Name:              "Returns error when application upsert failed",
  1336  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1337  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1338  				repo := &automock.ApplicationRepository{}
  1339  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return("", testErr).Once()
  1340  				return repo
  1341  			},
  1342  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1343  				repo := &automock.IntegrationSystemRepository{}
  1344  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1345  				return repo
  1346  			},
  1347  			LabelServiceFn: UnusedLabelService,
  1348  			LabelRepoFn:    UnusedLabelRepository,
  1349  			UIDServiceFn: func() *automock.UIDService {
  1350  				svc := &automock.UIDService{}
  1351  				svc.On("Generate").Return(id).Once()
  1352  				return svc
  1353  			},
  1354  			WebhookRepoFn:      UnusedWebhookRepository,
  1355  			FormationServiceFn: UnusedFormationService,
  1356  			GetInput: func() model.ApplicationRegisterInput {
  1357  				return applicationRegisterInputWithScenarios()
  1358  			},
  1359  			ExpectedErr: testErr,
  1360  		},
  1361  		{
  1362  			Name:              "Returns error when integration system doesn't exist",
  1363  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1364  			AppRepoFn: func(_ string) *automock.ApplicationRepository {
  1365  				return &automock.ApplicationRepository{}
  1366  			},
  1367  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1368  				repo := &automock.IntegrationSystemRepository{}
  1369  				repo.On("Exists", ctx, intSysID).Return(false, nil).Once()
  1370  				return repo
  1371  			},
  1372  			LabelServiceFn:     UnusedLabelService,
  1373  			LabelRepoFn:        UnusedLabelRepository,
  1374  			UIDServiceFn:       UnusedUIDService,
  1375  			WebhookRepoFn:      UnusedWebhookRepository,
  1376  			FormationServiceFn: UnusedFormationService,
  1377  			GetInput: func() model.ApplicationRegisterInput {
  1378  				return applicationRegisterInputWithScenarios()
  1379  			},
  1380  			ExpectedErr: errors.New("Object not found"),
  1381  		},
  1382  		{
  1383  			Name:              "Returns error when checking for integration system fails",
  1384  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1385  			AppRepoFn: func(_ string) *automock.ApplicationRepository {
  1386  				return &automock.ApplicationRepository{}
  1387  			},
  1388  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1389  				repo := &automock.IntegrationSystemRepository{}
  1390  				repo.On("Exists", ctx, intSysID).Return(false, testErr).Once()
  1391  				return repo
  1392  			},
  1393  			LabelServiceFn:     UnusedLabelService,
  1394  			LabelRepoFn:        UnusedLabelRepository,
  1395  			UIDServiceFn:       UnusedUIDService,
  1396  			WebhookRepoFn:      UnusedWebhookRepository,
  1397  			FormationServiceFn: UnusedFormationService,
  1398  			GetInput: func() model.ApplicationRegisterInput {
  1399  				return applicationRegisterInputWithScenarios()
  1400  			},
  1401  			ExpectedErr: testErr,
  1402  		},
  1403  		{
  1404  			Name:              "Should not create webhooks when application type is missing from input labels",
  1405  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1406  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1407  				repo := &automock.ApplicationRepository{}
  1408  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1409  				return repo
  1410  			},
  1411  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1412  				repo := &automock.IntegrationSystemRepository{}
  1413  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1414  				return repo
  1415  			},
  1416  			LabelServiceFn: func() *automock.LabelService {
  1417  				svc := &automock.LabelService{}
  1418  				labels := map[string]interface{}{
  1419  					"integrationSystemID":  intSysID,
  1420  					"label":                "value",
  1421  					"name":                 "mp-foo-bar-not",
  1422  					"ppmsProductVersionId": "1",
  1423  				}
  1424  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
  1425  				return svc
  1426  			},
  1427  			LabelRepoFn: UnusedLabelRepository,
  1428  			UIDServiceFn: func() *automock.UIDService {
  1429  				svc := &automock.UIDService{}
  1430  				svc.On("Generate").Return(id).Once()
  1431  				return svc
  1432  			},
  1433  			WebhookRepoFn:      UnusedWebhookRepository,
  1434  			FormationServiceFn: UnusedFormationService,
  1435  			OrdWebhookMapping:  ordWebhookMapping,
  1436  			GetInput: func() model.ApplicationRegisterInput {
  1437  				return modelInputWithoutApplicationType
  1438  			},
  1439  			ExpectedErr: nil,
  1440  		},
  1441  		{
  1442  			Name:              "Should not create webhooks when baseURL is missing from input",
  1443  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1444  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1445  				repo := &automock.ApplicationRepository{}
  1446  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1447  				return repo
  1448  			},
  1449  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1450  				repo := &automock.IntegrationSystemRepository{}
  1451  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1452  				return repo
  1453  			},
  1454  			LabelServiceFn: func() *automock.LabelService {
  1455  				svc := &automock.LabelService{}
  1456  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
  1457  				return svc
  1458  			},
  1459  			LabelRepoFn: func() *automock.LabelRepository {
  1460  				repo := &automock.LabelRepository{}
  1461  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.ApplicationLabel, "")).Once()
  1462  				return repo
  1463  			},
  1464  			UIDServiceFn: func() *automock.UIDService {
  1465  				svc := &automock.UIDService{}
  1466  				svc.On("Generate").Return(id).Once()
  1467  				return svc
  1468  			},
  1469  			WebhookRepoFn: UnusedWebhookRepository,
  1470  			FormationServiceFn: func() *automock.FormationService {
  1471  				svc := &automock.FormationService{}
  1472  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1473  				return svc
  1474  			},
  1475  			OrdWebhookMapping: ordWebhookMapping,
  1476  			GetInput: func() model.ApplicationRegisterInput {
  1477  				modelInputWithoutBaseURL := applicationRegisterInputWithScenarios()
  1478  				modelInputWithoutBaseURL.BaseURL = str.Ptr("")
  1479  				return modelInputWithoutBaseURL
  1480  			},
  1481  			ExpectedErr: nil,
  1482  		},
  1483  		{
  1484  			Name:              "Should not create webhooks when baseURL is invalid",
  1485  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1486  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1487  				repo := &automock.ApplicationRepository{}
  1488  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1489  				return repo
  1490  			},
  1491  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1492  				repo := &automock.IntegrationSystemRepository{}
  1493  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1494  				return repo
  1495  			},
  1496  			LabelServiceFn: func() *automock.LabelService {
  1497  				svc := &automock.LabelService{}
  1498  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
  1499  				return svc
  1500  			},
  1501  			LabelRepoFn: func() *automock.LabelRepository {
  1502  				repo := &automock.LabelRepository{}
  1503  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.ApplicationLabel, "")).Once()
  1504  				return repo
  1505  			},
  1506  			UIDServiceFn: func() *automock.UIDService {
  1507  				svc := &automock.UIDService{}
  1508  				svc.On("Generate").Return(id).Once()
  1509  				return svc
  1510  			},
  1511  			WebhookRepoFn: UnusedWebhookRepository,
  1512  			FormationServiceFn: func() *automock.FormationService {
  1513  				svc := &automock.FormationService{}
  1514  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1515  				return svc
  1516  			},
  1517  			OrdWebhookMapping: ordWebhookMapping,
  1518  			GetInput: func() model.ApplicationRegisterInput {
  1519  				modelInputWithInvalidBaseURL := applicationRegisterInputWithScenarios()
  1520  				modelInputWithInvalidBaseURL.BaseURL = str.Ptr("123://localhost")
  1521  				return modelInputWithInvalidBaseURL
  1522  			},
  1523  			ExpectedErr: nil,
  1524  		},
  1525  		{
  1526  			Name:              "Should not create webhooks when ppmsProductVersion is present in input but is not in configuration",
  1527  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1528  			AppRepoFn: func(upsertMethodName string) *automock.ApplicationRepository {
  1529  				repo := &automock.ApplicationRepository{}
  1530  				repo.On(upsertMethodName, ctx, mock.Anything, mock.MatchedBy(appModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1531  				return repo
  1532  			},
  1533  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1534  				repo := &automock.IntegrationSystemRepository{}
  1535  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1536  				return repo
  1537  			},
  1538  			LabelServiceFn: func() *automock.LabelService {
  1539  				svc := &automock.LabelService{}
  1540  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labelsWithInvalidPpmsProductVersion).Return(nil).Once()
  1541  				return svc
  1542  			},
  1543  			LabelRepoFn: func() *automock.LabelRepository {
  1544  				repo := &automock.LabelRepository{}
  1545  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.ApplicationLabel, "")).Once()
  1546  				return repo
  1547  			},
  1548  			UIDServiceFn: func() *automock.UIDService {
  1549  				svc := &automock.UIDService{}
  1550  				svc.On("Generate").Return(id).Once()
  1551  				return svc
  1552  			},
  1553  			WebhookRepoFn: UnusedWebhookRepository,
  1554  			FormationServiceFn: func() *automock.FormationService {
  1555  				svc := &automock.FormationService{}
  1556  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1557  				return svc
  1558  			},
  1559  			OrdWebhookMapping: ordWebhookMapping,
  1560  			GetInput: func() model.ApplicationRegisterInput {
  1561  				modelInputWithInvalidPpmsProductVersion := applicationRegisterInputWithScenarios()
  1562  				modelInputWithInvalidPpmsProductVersion.Labels["ppmsProductVersionId"] = "2"
  1563  				modelInputWithInvalidPpmsProductVersion.BaseURL = str.Ptr("123://localhost")
  1564  				return modelInputWithInvalidPpmsProductVersion
  1565  			},
  1566  			ExpectedErr: nil,
  1567  		},
  1568  	}
  1569  
  1570  	for _, testCase := range testCases {
  1571  		t.Run(testCase.Name+"_Upsert", func(t *testing.T) {
  1572  			appNameNormalizer := testCase.AppNameNormalizer
  1573  			appRepo := testCase.AppRepoFn("Upsert")
  1574  			labelSvc := testCase.LabelServiceFn()
  1575  			labelRepo := testCase.LabelRepoFn()
  1576  			uidSvc := testCase.UIDServiceFn()
  1577  			intSysRepo := testCase.IntSysRepoFn()
  1578  			webhookRepo := testCase.WebhookRepoFn()
  1579  			formationService := testCase.FormationServiceFn()
  1580  			svc := application.NewService(appNameNormalizer, nil, appRepo, webhookRepo, nil, labelRepo, intSysRepo, labelSvc, nil, uidSvc, formationService, "", testCase.OrdWebhookMapping)
  1581  			svc.SetTimestampGen(func() time.Time { return timestamp })
  1582  
  1583  			// when
  1584  			err := svc.Upsert(ctx, testCase.GetInput())
  1585  
  1586  			// then
  1587  			if testCase.ExpectedErr != nil {
  1588  				require.NotNil(t, err)
  1589  				assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
  1590  			} else {
  1591  				require.Nil(t, err)
  1592  			}
  1593  
  1594  			mock.AssertExpectationsForObjects(t, appRepo, labelSvc, labelRepo, uidSvc, intSysRepo, webhookRepo, formationService)
  1595  		})
  1596  
  1597  		t.Run(testCase.Name+"_TrustedUpsert", func(t *testing.T) {
  1598  			appNameNormalizer := testCase.AppNameNormalizer
  1599  			appRepo := testCase.AppRepoFn("TrustedUpsert")
  1600  			labelSvc := testCase.LabelServiceFn()
  1601  			labelRepo := testCase.LabelRepoFn()
  1602  			uidSvc := testCase.UIDServiceFn()
  1603  			intSysRepo := testCase.IntSysRepoFn()
  1604  			webhookRepo := testCase.WebhookRepoFn()
  1605  			formationService := testCase.FormationServiceFn()
  1606  			svc := application.NewService(appNameNormalizer, nil, appRepo, webhookRepo, nil, labelRepo, intSysRepo, labelSvc, nil, uidSvc, formationService, "", testCase.OrdWebhookMapping)
  1607  			svc.SetTimestampGen(func() time.Time { return timestamp })
  1608  
  1609  			// when
  1610  			err := svc.TrustedUpsert(ctx, testCase.GetInput())
  1611  
  1612  			// then
  1613  			if testCase.ExpectedErr != nil {
  1614  				require.NotNil(t, err)
  1615  				assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
  1616  			} else {
  1617  				require.Nil(t, err)
  1618  			}
  1619  
  1620  			mock.AssertExpectationsForObjects(t, appRepo, labelSvc, labelRepo, uidSvc, intSysRepo, webhookRepo, formationService)
  1621  		})
  1622  	}
  1623  
  1624  	t.Run("Returns error on loading tenant", func(t *testing.T) {
  1625  		svc := application.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  1626  		// when
  1627  		_, err := svc.Create(context.TODO(), model.ApplicationRegisterInput{})
  1628  		assert.True(t, apperrors.IsCannotReadTenant(err))
  1629  	})
  1630  }
  1631  
  1632  func TestService_TrustedUpsertFromTemplate(t *testing.T) {
  1633  	// given
  1634  	timestamp := time.Now()
  1635  	testErr := errors.New("Test error")
  1636  	modelInput := applicationRegisterInputWithScenarios()
  1637  
  1638  	normalizedModelInput := model.ApplicationRegisterInput{
  1639  		Name: "mp-foo-bar-not",
  1640  		Webhooks: []*model.WebhookInput{
  1641  			{URL: stringPtr("test.foo.com")},
  1642  			{URL: stringPtr("test.bar.com")},
  1643  		},
  1644  
  1645  		Labels: map[string]interface{}{
  1646  			"label": "value",
  1647  		},
  1648  		IntegrationSystemID: &intSysID,
  1649  	}
  1650  	normalizedModelInput.Bundles = modelInput.Bundles
  1651  
  1652  	labels := map[string]interface{}{
  1653  		"integrationSystemID":  intSysID,
  1654  		"label":                "value",
  1655  		"name":                 "mp-foo-bar-not",
  1656  		"applicationType":      "test-app-with-ppms",
  1657  		"ppmsProductVersionId": "1",
  1658  	}
  1659  	labelsWithoutIntSys := map[string]interface{}{
  1660  		"integrationSystemID": "",
  1661  		"name":                "mp-test",
  1662  	}
  1663  	var nilLabels map[string]interface{}
  1664  
  1665  	id := "foo"
  1666  
  1667  	tnt := "tenant"
  1668  	externalTnt := "external-tnt"
  1669  	appTemplteID := "test-app-template"
  1670  
  1671  	ordWebhookMapping := []application.ORDWebhookMapping{
  1672  		{
  1673  			Type: "test-app",
  1674  		},
  1675  		{
  1676  			Type:                "test-app-with-ppms",
  1677  			PpmsProductVersions: []string{"1"},
  1678  		},
  1679  	}
  1680  
  1681  	appFromTemplateModel := modelFromInput(modelInput, tnt, id, applicationFromTemplateMatcher(modelInput.Name, modelInput.Description, &appTemplteID))
  1682  
  1683  	ctx := context.TODO()
  1684  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  1685  
  1686  	testCases := []struct {
  1687  		Name               string
  1688  		AppNameNormalizer  normalizer.Normalizator
  1689  		AppRepoFn          func() *automock.ApplicationRepository
  1690  		IntSysRepoFn       func() *automock.IntegrationSystemRepository
  1691  		LabelServiceFn     func() *automock.LabelService
  1692  		LabelRepoFn        func() *automock.LabelRepository
  1693  		UIDServiceFn       func() *automock.UIDService
  1694  		WebhookRepoFn      func() *automock.WebhookRepository
  1695  		FormationServiceFn func() *automock.FormationService
  1696  		Input              model.ApplicationRegisterInput
  1697  		OrdWebhookMapping  []application.ORDWebhookMapping
  1698  		ExpectedErr        error
  1699  	}{
  1700  		{
  1701  			Name:              "Success",
  1702  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1703  			AppRepoFn: func() *automock.ApplicationRepository {
  1704  				repo := &automock.ApplicationRepository{}
  1705  				repo.On("TrustedUpsert", ctx, mock.Anything, mock.MatchedBy(appFromTemplateModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1706  				return repo
  1707  			},
  1708  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1709  				repo := &automock.IntegrationSystemRepository{}
  1710  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1711  				return repo
  1712  			},
  1713  			LabelServiceFn: func() *automock.LabelService {
  1714  				svc := &automock.LabelService{}
  1715  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
  1716  				return svc
  1717  			},
  1718  			LabelRepoFn: func() *automock.LabelRepository {
  1719  				repo := &automock.LabelRepository{}
  1720  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.ApplicationLabel, "")).Once()
  1721  				return repo
  1722  			},
  1723  			UIDServiceFn: func() *automock.UIDService {
  1724  				svc := &automock.UIDService{}
  1725  				svc.On("Generate").Return(id)
  1726  				return svc
  1727  			},
  1728  			WebhookRepoFn: func() *automock.WebhookRepository {
  1729  				wh := &model.Webhook{
  1730  					URL:      stringPtr("test.foo.com"),
  1731  					ObjectID: id,
  1732  				}
  1733  				webhookRepo := &automock.WebhookRepository{}
  1734  				webhookRepo.On("ListByReferenceObjectID", ctx, tnt, id, model.ApplicationWebhookReference).Return([]*model.Webhook{wh}, nil)
  1735  				webhookRepo.On("CreateMany", ctx, tnt, mock.AnythingOfType("[]*model.Webhook")).Return(nil)
  1736  				return webhookRepo
  1737  			},
  1738  			FormationServiceFn: func() *automock.FormationService {
  1739  				svc := &automock.FormationService{}
  1740  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1741  				return svc
  1742  			},
  1743  			OrdWebhookMapping: ordWebhookMapping,
  1744  			Input:             applicationRegisterInputWithScenarios(),
  1745  			ExpectedErr:       nil,
  1746  		},
  1747  		{
  1748  			Name:              "Success when no labels provided",
  1749  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1750  			AppRepoFn: func() *automock.ApplicationRepository {
  1751  				repo := &automock.ApplicationRepository{}
  1752  				repo.On("TrustedUpsert", ctx, mock.Anything, mock.MatchedBy(applicationMatcher("test", nil))).Return("foo", nil).Once()
  1753  				return repo
  1754  			},
  1755  			IntSysRepoFn: UnusedIntegrationSystemRepository,
  1756  			LabelServiceFn: func() *automock.LabelService {
  1757  				svc := &automock.LabelService{}
  1758  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labelsWithoutIntSys).Return(nil).Once()
  1759  				return svc
  1760  			},
  1761  			LabelRepoFn: UnusedLabelRepository,
  1762  			UIDServiceFn: func() *automock.UIDService {
  1763  				svc := &automock.UIDService{}
  1764  				svc.On("Generate").Return(id)
  1765  				return svc
  1766  			},
  1767  			WebhookRepoFn:      UnusedWebhookRepository,
  1768  			FormationServiceFn: UnusedFormationService,
  1769  			Input:              model.ApplicationRegisterInput{Name: "test", Labels: nilLabels},
  1770  			ExpectedErr:        nil,
  1771  		},
  1772  		{
  1773  			Name:              "Success when scenarios label is not provided",
  1774  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1775  			AppRepoFn: func() *automock.ApplicationRepository {
  1776  				repo := &automock.ApplicationRepository{}
  1777  				repo.On("TrustedUpsert", ctx, mock.Anything, mock.MatchedBy(applicationMatcher("test", nil))).Return("foo", nil).Once()
  1778  				return repo
  1779  			},
  1780  			IntSysRepoFn: UnusedIntegrationSystemRepository,
  1781  			LabelServiceFn: func() *automock.LabelService {
  1782  				svc := &automock.LabelService{}
  1783  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labelsWithoutIntSys).Return(nil).Once()
  1784  				return svc
  1785  			},
  1786  			LabelRepoFn: UnusedLabelRepository,
  1787  			UIDServiceFn: func() *automock.UIDService {
  1788  				svc := &automock.UIDService{}
  1789  				svc.On("Generate").Return(id)
  1790  				return svc
  1791  			},
  1792  			WebhookRepoFn: UnusedWebhookRepository,
  1793  			FormationServiceFn: func() *automock.FormationService {
  1794  				svc := &automock.FormationService{}
  1795  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1796  				return svc
  1797  			},
  1798  			Input: model.ApplicationRegisterInput{
  1799  				Name:   "test",
  1800  				Labels: labelsWithoutIntSys,
  1801  			},
  1802  			ExpectedErr: nil,
  1803  		},
  1804  		{
  1805  			Name:              "Returns error when listing webhooks",
  1806  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1807  			AppRepoFn: func() *automock.ApplicationRepository {
  1808  				repo := &automock.ApplicationRepository{}
  1809  				repo.On("TrustedUpsert", ctx, mock.Anything, mock.MatchedBy(appFromTemplateModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1810  				return repo
  1811  			},
  1812  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1813  				repo := &automock.IntegrationSystemRepository{}
  1814  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1815  				return repo
  1816  			},
  1817  			LabelServiceFn: func() *automock.LabelService {
  1818  				svc := &automock.LabelService{}
  1819  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, labels).Return(nil).Once()
  1820  				return svc
  1821  			},
  1822  			LabelRepoFn: func() *automock.LabelRepository {
  1823  				repo := &automock.LabelRepository{}
  1824  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.ApplicationLabel, "")).Once()
  1825  				return repo
  1826  			},
  1827  			UIDServiceFn: func() *automock.UIDService {
  1828  				svc := &automock.UIDService{}
  1829  				svc.On("Generate").Return(id)
  1830  				return svc
  1831  			},
  1832  			WebhookRepoFn: func() *automock.WebhookRepository {
  1833  				webhookRepo := &automock.WebhookRepository{}
  1834  				webhookRepo.On("ListByReferenceObjectID", ctx, tnt, id, model.ApplicationWebhookReference).Return(nil, testErr)
  1835  				return webhookRepo
  1836  			},
  1837  			FormationServiceFn: func() *automock.FormationService {
  1838  				svc := &automock.FormationService{}
  1839  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1840  				return svc
  1841  			},
  1842  			OrdWebhookMapping: ordWebhookMapping,
  1843  			Input:             modelInput,
  1844  			ExpectedErr:       testErr,
  1845  		},
  1846  		{
  1847  			Name:              "Returns error when creating webhooks",
  1848  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1849  			AppRepoFn: func() *automock.ApplicationRepository {
  1850  				repo := &automock.ApplicationRepository{}
  1851  				repo.On("TrustedUpsert", ctx, mock.Anything, mock.MatchedBy(appFromTemplateModel.ApplicationMatcherFn)).Return("foo", nil).Once()
  1852  				return repo
  1853  			},
  1854  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1855  				repo := &automock.IntegrationSystemRepository{}
  1856  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1857  				return repo
  1858  			},
  1859  			LabelServiceFn: func() *automock.LabelService {
  1860  				svc := &automock.LabelService{}
  1861  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, id, map[string]interface{}{
  1862  					"integrationSystemID": intSysID,
  1863  					"label":               "value",
  1864  					"name":                "mp-foo-bar-not",
  1865  					"applicationType":     "test-app",
  1866  				}).Return(nil).Once()
  1867  				return svc
  1868  			},
  1869  			LabelRepoFn: UnusedLabelRepository,
  1870  			UIDServiceFn: func() *automock.UIDService {
  1871  				svc := &automock.UIDService{}
  1872  				svc.On("Generate").Return(id)
  1873  				return svc
  1874  			},
  1875  			WebhookRepoFn: func() *automock.WebhookRepository {
  1876  				webhookRepo := &automock.WebhookRepository{}
  1877  				webhookRepo.On("ListByReferenceObjectID", ctx, tnt, id, model.ApplicationWebhookReference).Return([]*model.Webhook{}, nil)
  1878  				webhookRepo.On("CreateMany", ctx, tnt, mock.AnythingOfType("[]*model.Webhook")).Return(testErr)
  1879  				return webhookRepo
  1880  			},
  1881  			FormationServiceFn: UnusedFormationService,
  1882  			OrdWebhookMapping:  ordWebhookMapping,
  1883  			Input: model.ApplicationRegisterInput{
  1884  				Name: "foo.bar-not",
  1885  				Labels: map[string]interface{}{
  1886  					"label":           "value",
  1887  					"applicationType": "test-app",
  1888  				},
  1889  				IntegrationSystemID: &intSysID,
  1890  				BaseURL:             str.Ptr("http://localhost.com"),
  1891  			},
  1892  			ExpectedErr: testErr,
  1893  		},
  1894  		{
  1895  			Name:              "Returns error when application trusted upsert failed",
  1896  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1897  			AppRepoFn: func() *automock.ApplicationRepository {
  1898  				repo := &automock.ApplicationRepository{}
  1899  				repo.On("TrustedUpsert", ctx, mock.Anything, mock.MatchedBy(appFromTemplateModel.ApplicationMatcherFn)).Return("", testErr).Once()
  1900  				return repo
  1901  			},
  1902  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1903  				repo := &automock.IntegrationSystemRepository{}
  1904  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  1905  				return repo
  1906  			},
  1907  			LabelServiceFn: UnusedLabelService,
  1908  			LabelRepoFn:    UnusedLabelRepository,
  1909  			UIDServiceFn: func() *automock.UIDService {
  1910  				svc := &automock.UIDService{}
  1911  				svc.On("Generate").Return(id).Once()
  1912  				return svc
  1913  			},
  1914  			FormationServiceFn: func() *automock.FormationService {
  1915  				svc := &automock.FormationService{}
  1916  				svc.On("AssignFormation", ctx, tnt, id, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  1917  				return svc
  1918  			},
  1919  			WebhookRepoFn: UnusedWebhookRepository,
  1920  			Input:         applicationRegisterInputWithScenarios(),
  1921  			ExpectedErr:   testErr,
  1922  		},
  1923  		{
  1924  			Name:              "Returns error when integration system doesn't exist",
  1925  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1926  			AppRepoFn: func() *automock.ApplicationRepository {
  1927  				return &automock.ApplicationRepository{}
  1928  			},
  1929  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1930  				repo := &automock.IntegrationSystemRepository{}
  1931  				repo.On("Exists", ctx, intSysID).Return(false, nil).Once()
  1932  				return repo
  1933  			},
  1934  			LabelServiceFn:     UnusedLabelService,
  1935  			LabelRepoFn:        UnusedLabelRepository,
  1936  			UIDServiceFn:       UnusedUIDService,
  1937  			WebhookRepoFn:      UnusedWebhookRepository,
  1938  			FormationServiceFn: UnusedFormationService,
  1939  			Input:              applicationRegisterInputWithScenarios(),
  1940  			ExpectedErr:        errors.New("Object not found"),
  1941  		},
  1942  		{
  1943  			Name:              "Returns error when checking for integration system fails",
  1944  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  1945  			AppRepoFn: func() *automock.ApplicationRepository {
  1946  				return &automock.ApplicationRepository{}
  1947  			},
  1948  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  1949  				repo := &automock.IntegrationSystemRepository{}
  1950  				repo.On("Exists", ctx, intSysID).Return(false, testErr).Once()
  1951  				return repo
  1952  			},
  1953  			LabelServiceFn:     UnusedLabelService,
  1954  			LabelRepoFn:        UnusedLabelRepository,
  1955  			UIDServiceFn:       UnusedUIDService,
  1956  			WebhookRepoFn:      UnusedWebhookRepository,
  1957  			FormationServiceFn: UnusedFormationService,
  1958  			Input:              applicationRegisterInputWithScenarios(),
  1959  			ExpectedErr:        testErr,
  1960  		},
  1961  	}
  1962  
  1963  	for _, testCase := range testCases {
  1964  		t.Run(testCase.Name, func(t *testing.T) {
  1965  			appNameNormalizer := testCase.AppNameNormalizer
  1966  			appRepo := testCase.AppRepoFn()
  1967  			labelSvc := testCase.LabelServiceFn()
  1968  			labelRepo := testCase.LabelRepoFn()
  1969  			uidSvc := testCase.UIDServiceFn()
  1970  			intSysRepo := testCase.IntSysRepoFn()
  1971  			webhookRepo := testCase.WebhookRepoFn()
  1972  			formationService := testCase.FormationServiceFn()
  1973  			svc := application.NewService(appNameNormalizer, nil, appRepo, webhookRepo, nil, labelRepo, intSysRepo, labelSvc, nil, uidSvc, formationService, "", testCase.OrdWebhookMapping)
  1974  			svc.SetTimestampGen(func() time.Time { return timestamp })
  1975  
  1976  			// when
  1977  			err := svc.TrustedUpsertFromTemplate(ctx, testCase.Input, &appTemplteID)
  1978  
  1979  			// then
  1980  			if testCase.ExpectedErr != nil {
  1981  				require.NotNil(t, err)
  1982  				assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
  1983  			} else {
  1984  				require.Nil(t, err)
  1985  			}
  1986  
  1987  			mock.AssertExpectationsForObjects(t, appRepo, labelSvc, labelRepo, uidSvc, intSysRepo, webhookRepo)
  1988  		})
  1989  	}
  1990  
  1991  	t.Run("Returns error on loading tenant", func(t *testing.T) {
  1992  		svc := application.NewService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  1993  		// when
  1994  		_, err := svc.Create(context.TODO(), model.ApplicationRegisterInput{})
  1995  		assert.True(t, apperrors.IsCannotReadTenant(err))
  1996  	})
  1997  }
  1998  
  1999  func TestService_Update(t *testing.T) {
  2000  	// GIVEN
  2001  	testErr := errors.New("Test error")
  2002  
  2003  	id := "foo"
  2004  	tnt := "tenant"
  2005  	externalTnt := "external-tnt"
  2006  	conditionTimestamp := time.Now()
  2007  	timestampGenFunc := func() time.Time { return conditionTimestamp }
  2008  
  2009  	var updateInput model.ApplicationUpdateInput
  2010  	var applicationModelBefore *model.Application
  2011  	var applicationModelAfter *model.Application
  2012  	var intSysLabel *model.LabelInput
  2013  	var nameLabel *model.LabelInput
  2014  	var updateInputStatusOnly model.ApplicationUpdateInput
  2015  	var applicationModelAfterStatusUpdate *model.Application
  2016  
  2017  	appTypeLabel := &model.Label{
  2018  		Key:   "applicationType",
  2019  		Value: "test-app",
  2020  	}
  2021  	ppmsVersionIDLabel := &model.Label{
  2022  		Key:   "ppmsProductVersionId",
  2023  		Value: "1",
  2024  	}
  2025  	ordWebhookMapping := []application.ORDWebhookMapping{
  2026  		{
  2027  			Type:                "test-app",
  2028  			PpmsProductVersions: []string{"1"},
  2029  			SubdomainSuffix:     "-test",
  2030  		},
  2031  	}
  2032  
  2033  	ctx := context.TODO()
  2034  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  2035  
  2036  	resetModels := func() {
  2037  		appName := "initialn"
  2038  		initialDescrription := "initald"
  2039  		initialURL := "initialu"
  2040  		updatedDescription := "updatedd"
  2041  		updatedHealthCheckURL := "updatedhcu"
  2042  		updatedBaseURL := "updatedbu"
  2043  		updatedApplicationNamespace := "updatedappns"
  2044  		updateInput = fixModelApplicationUpdateInput(appName, updatedDescription, updatedHealthCheckURL, updatedBaseURL, updatedApplicationNamespace, model.ApplicationStatusConditionConnected)
  2045  		applicationModelBefore = fixModelApplicationWithAllUpdatableFields(id, appName, initialDescrription, initialURL, nil, nil, model.ApplicationStatusConditionConnected, conditionTimestamp)
  2046  		applicationModelAfter = fixModelApplicationWithAllUpdatableFields(id, appName, updatedDescription, updatedHealthCheckURL, &updatedBaseURL, &updatedApplicationNamespace, model.ApplicationStatusConditionConnected, conditionTimestamp)
  2047  		intSysLabel = fixLabelInput("integrationSystemID", intSysID, id, model.ApplicationLabelableObject)
  2048  		intSysLabel.Version = 0
  2049  		nameLabel = fixLabelInput("name", "mp-"+appName, id, model.ApplicationLabelableObject)
  2050  		updateInputStatusOnly = fixModelApplicationUpdateInputStatus(model.ApplicationStatusConditionConnected)
  2051  		applicationModelAfterStatusUpdate = fixModelApplicationWithAllUpdatableFields(id, appName, initialDescrription, initialURL, nil, nil, model.ApplicationStatusConditionConnected, conditionTimestamp)
  2052  	}
  2053  
  2054  	resetModels()
  2055  
  2056  	testCases := []struct {
  2057  		Name               string
  2058  		AppNameNormalizer  normalizer.Normalizator
  2059  		AppRepoFn          func() *automock.ApplicationRepository
  2060  		IntSysRepoFn       func() *automock.IntegrationSystemRepository
  2061  		LabelSvcFn         func() *automock.LabelService
  2062  		WebhookRepoFn      func() *automock.WebhookRepository
  2063  		UIDServiceFn       func() *automock.UIDService
  2064  		Input              model.ApplicationUpdateInput
  2065  		InputID            string
  2066  		ORDWebhookMapping  []application.ORDWebhookMapping
  2067  		ExpectedErrMessage string
  2068  	}{
  2069  		{
  2070  			Name:              "Success",
  2071  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2072  			AppRepoFn: func() *automock.ApplicationRepository {
  2073  				repo := &automock.ApplicationRepository{}
  2074  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2075  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2076  				repo.On("Exists", ctx, tnt, id).Return(true, nil).Twice()
  2077  				return repo
  2078  			},
  2079  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2080  				repo := &automock.IntegrationSystemRepository{}
  2081  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2082  				return repo
  2083  			},
  2084  			LabelSvcFn: func() *automock.LabelService {
  2085  				svc := &automock.LabelService{}
  2086  				svc.On("UpsertLabel", ctx, tnt, intSysLabel).Return(nil).Once()
  2087  				svc.On("UpsertLabel", ctx, tnt, nameLabel).Return(nil).Once()
  2088  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "applicationType").Return(appTypeLabel, nil).Once()
  2089  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "ppmsProductVersionId").Return(ppmsVersionIDLabel, nil).Once()
  2090  				return svc
  2091  			},
  2092  			WebhookRepoFn: func() *automock.WebhookRepository {
  2093  				webhookRepo := &automock.WebhookRepository{}
  2094  				wh := &model.Webhook{
  2095  					URL:      stringPtr("test.foo.com"),
  2096  					ObjectID: id,
  2097  				}
  2098  				webhookRepo.On("ListByReferenceObjectID", ctx, tnt, id, model.ApplicationWebhookReference).Return([]*model.Webhook{wh}, nil)
  2099  				webhookRepo.On("CreateMany", ctx, tnt, mock.AnythingOfType("[]*model.Webhook")).Return(nil)
  2100  				return webhookRepo
  2101  			},
  2102  			UIDServiceFn: func() *automock.UIDService {
  2103  				svc := &automock.UIDService{}
  2104  				svc.On("Generate").Return(id)
  2105  				return svc
  2106  			},
  2107  			InputID:            "foo",
  2108  			ORDWebhookMapping:  ordWebhookMapping,
  2109  			Input:              updateInput,
  2110  			ExpectedErrMessage: "",
  2111  		},
  2112  		{
  2113  			Name:              "Success Status Condition Update",
  2114  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2115  			AppRepoFn: func() *automock.ApplicationRepository {
  2116  				repo := &automock.ApplicationRepository{}
  2117  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2118  				repo.On("Update", ctx, tnt, applicationModelAfterStatusUpdate).Return(nil).Once()
  2119  				repo.On("Exists", ctx, tnt, id).Return(true, nil).Once()
  2120  				return repo
  2121  			},
  2122  			IntSysRepoFn: UnusedIntegrationSystemRepository,
  2123  			LabelSvcFn: func() *automock.LabelService {
  2124  				svc := &automock.LabelService{}
  2125  				svc.On("UpsertLabel", ctx, tnt, nameLabel).Return(nil).Once()
  2126  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "applicationType").Return(appTypeLabel, nil).Once()
  2127  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "ppmsProductVersionId").Return(ppmsVersionIDLabel, nil).Once()
  2128  				return svc
  2129  			},
  2130  			WebhookRepoFn:      UnusedWebhookRepository,
  2131  			UIDServiceFn:       UnusedUIDService,
  2132  			InputID:            "foo",
  2133  			Input:              updateInputStatusOnly,
  2134  			ExpectedErrMessage: "",
  2135  		},
  2136  		{
  2137  			Name:              "Returns error when application update failed",
  2138  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2139  			AppRepoFn: func() *automock.ApplicationRepository {
  2140  				repo := &automock.ApplicationRepository{}
  2141  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2142  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(testErr).Once()
  2143  				return repo
  2144  			},
  2145  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2146  				repo := &automock.IntegrationSystemRepository{}
  2147  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2148  				return repo
  2149  			},
  2150  			LabelSvcFn:         UnusedLabelUpsertService,
  2151  			WebhookRepoFn:      UnusedWebhookRepository,
  2152  			UIDServiceFn:       UnusedUIDService,
  2153  			InputID:            "foo",
  2154  			Input:              updateInput,
  2155  			ExpectedErrMessage: testErr.Error(),
  2156  		},
  2157  		{
  2158  			Name:              "Returns error when application retrieval failed",
  2159  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2160  			AppRepoFn: func() *automock.ApplicationRepository {
  2161  				repo := &automock.ApplicationRepository{}
  2162  				repo.On("GetByID", ctx, tnt, id).Return(nil, testErr).Once()
  2163  				return repo
  2164  			},
  2165  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2166  				repo := &automock.IntegrationSystemRepository{}
  2167  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2168  				return repo
  2169  			},
  2170  			LabelSvcFn:         UnusedLabelUpsertService,
  2171  			WebhookRepoFn:      UnusedWebhookRepository,
  2172  			UIDServiceFn:       UnusedUIDService,
  2173  			InputID:            "foo",
  2174  			Input:              updateInput,
  2175  			ExpectedErrMessage: testErr.Error(),
  2176  		},
  2177  		{
  2178  			Name:              "Returns error when Integration System does not exist",
  2179  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2180  			AppRepoFn:         UnusedApplicationRepository,
  2181  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2182  				repo := &automock.IntegrationSystemRepository{}
  2183  				repo.On("Exists", ctx, intSysID).Return(false, nil).Once()
  2184  				return repo
  2185  			},
  2186  			LabelSvcFn:         UnusedLabelUpsertService,
  2187  			WebhookRepoFn:      UnusedWebhookRepository,
  2188  			UIDServiceFn:       UnusedUIDService,
  2189  			InputID:            "foo",
  2190  			Input:              updateInput,
  2191  			ExpectedErrMessage: errors.New("Object not found").Error(),
  2192  		},
  2193  		{
  2194  			Name:              "Returns error ensuring Integration System existence failed",
  2195  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2196  			AppRepoFn:         UnusedApplicationRepository,
  2197  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2198  				repo := &automock.IntegrationSystemRepository{}
  2199  				repo.On("Exists", ctx, intSysID).Return(false, testErr).Once()
  2200  				return repo
  2201  			},
  2202  			LabelSvcFn:         UnusedLabelUpsertService,
  2203  			WebhookRepoFn:      UnusedWebhookRepository,
  2204  			UIDServiceFn:       UnusedUIDService,
  2205  			InputID:            "foo",
  2206  			Input:              updateInput,
  2207  			ExpectedErrMessage: testErr.Error(),
  2208  		},
  2209  		{
  2210  			Name:              "Returns error when setting label fails",
  2211  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2212  			AppRepoFn: func() *automock.ApplicationRepository {
  2213  				repo := &automock.ApplicationRepository{}
  2214  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2215  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2216  				repo.On("Exists", ctx, tnt, id).Return(true, nil).Once()
  2217  				return repo
  2218  			},
  2219  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2220  				repo := &automock.IntegrationSystemRepository{}
  2221  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2222  				return repo
  2223  			},
  2224  			LabelSvcFn: func() *automock.LabelService {
  2225  				svc := &automock.LabelService{}
  2226  				svc.On("UpsertLabel", ctx, tnt, intSysLabel).Return(testErr).Once()
  2227  				return svc
  2228  			},
  2229  			WebhookRepoFn:      UnusedWebhookRepository,
  2230  			UIDServiceFn:       UnusedUIDService,
  2231  			InputID:            "foo",
  2232  			Input:              updateInput,
  2233  			ExpectedErrMessage: testErr.Error(),
  2234  		},
  2235  		{
  2236  			Name:              "Returns error when app does not exist",
  2237  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2238  			AppRepoFn: func() *automock.ApplicationRepository {
  2239  				repo := &automock.ApplicationRepository{}
  2240  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2241  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2242  				repo.On("Exists", ctx, tnt, id).Return(false, nil).Once()
  2243  				return repo
  2244  			},
  2245  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2246  				repo := &automock.IntegrationSystemRepository{}
  2247  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2248  				return repo
  2249  			},
  2250  			LabelSvcFn:         UnusedLabelUpsertService,
  2251  			WebhookRepoFn:      UnusedWebhookRepository,
  2252  			UIDServiceFn:       UnusedUIDService,
  2253  			InputID:            "foo",
  2254  			Input:              updateInput,
  2255  			ExpectedErrMessage: "Object not found",
  2256  		},
  2257  		{
  2258  			Name:              "Returns error when ensuring app existence fails",
  2259  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2260  			AppRepoFn: func() *automock.ApplicationRepository {
  2261  				repo := &automock.ApplicationRepository{}
  2262  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2263  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2264  				repo.On("Exists", ctx, tnt, id).Return(false, testErr).Once()
  2265  				return repo
  2266  			},
  2267  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2268  				repo := &automock.IntegrationSystemRepository{}
  2269  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2270  				return repo
  2271  			},
  2272  			LabelSvcFn:         UnusedLabelUpsertService,
  2273  			WebhookRepoFn:      UnusedWebhookRepository,
  2274  			UIDServiceFn:       UnusedUIDService,
  2275  			InputID:            "foo",
  2276  			Input:              updateInput,
  2277  			ExpectedErrMessage: testErr.Error(),
  2278  		},
  2279  		{
  2280  			Name:              "Should return error when fetching applicationType label",
  2281  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2282  			AppRepoFn: func() *automock.ApplicationRepository {
  2283  				repo := &automock.ApplicationRepository{}
  2284  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2285  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2286  				repo.On("Exists", ctx, tnt, id).Return(true, nil).Twice()
  2287  				return repo
  2288  			},
  2289  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2290  				repo := &automock.IntegrationSystemRepository{}
  2291  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2292  				return repo
  2293  			},
  2294  			LabelSvcFn: func() *automock.LabelService {
  2295  				svc := &automock.LabelService{}
  2296  				svc.On("UpsertLabel", ctx, tnt, intSysLabel).Return(nil).Once()
  2297  				svc.On("UpsertLabel", ctx, tnt, nameLabel).Return(nil).Once()
  2298  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "applicationType").Return(nil, testErr).Once()
  2299  				return svc
  2300  			},
  2301  			WebhookRepoFn:      UnusedWebhookRepository,
  2302  			UIDServiceFn:       UnusedUIDService,
  2303  			InputID:            "foo",
  2304  			Input:              updateInput,
  2305  			ExpectedErrMessage: testErr.Error(),
  2306  		},
  2307  		{
  2308  			Name:              "Should not create webhooks when applicationType label is missing",
  2309  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2310  			AppRepoFn: func() *automock.ApplicationRepository {
  2311  				repo := &automock.ApplicationRepository{}
  2312  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2313  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2314  				repo.On("Exists", ctx, tnt, id).Return(true, nil).Twice()
  2315  				return repo
  2316  			},
  2317  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2318  				repo := &automock.IntegrationSystemRepository{}
  2319  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2320  				return repo
  2321  			},
  2322  			LabelSvcFn: func() *automock.LabelService {
  2323  				svc := &automock.LabelService{}
  2324  				svc.On("UpsertLabel", ctx, tnt, intSysLabel).Return(nil).Once()
  2325  				svc.On("UpsertLabel", ctx, tnt, nameLabel).Return(nil).Once()
  2326  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "applicationType").Return(nil, apperrors.NewNotFoundErrorWithType(resource.Label)).Once()
  2327  				return svc
  2328  			},
  2329  			WebhookRepoFn:      UnusedWebhookRepository,
  2330  			UIDServiceFn:       UnusedUIDService,
  2331  			InputID:            "foo",
  2332  			Input:              updateInput,
  2333  			ExpectedErrMessage: "",
  2334  		},
  2335  		{
  2336  			Name:              "Should return error when fetching applicationType label",
  2337  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2338  			AppRepoFn: func() *automock.ApplicationRepository {
  2339  				repo := &automock.ApplicationRepository{}
  2340  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2341  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2342  				repo.On("Exists", ctx, tnt, id).Return(true, nil).Twice()
  2343  				return repo
  2344  			},
  2345  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2346  				repo := &automock.IntegrationSystemRepository{}
  2347  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2348  				return repo
  2349  			},
  2350  			LabelSvcFn: func() *automock.LabelService {
  2351  				svc := &automock.LabelService{}
  2352  				svc.On("UpsertLabel", ctx, tnt, intSysLabel).Return(nil).Once()
  2353  				svc.On("UpsertLabel", ctx, tnt, nameLabel).Return(nil).Once()
  2354  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "applicationType").Return(appTypeLabel, nil).Once()
  2355  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "ppmsProductVersionId").Return(nil, testErr).Once()
  2356  				return svc
  2357  			},
  2358  			WebhookRepoFn:      UnusedWebhookRepository,
  2359  			UIDServiceFn:       UnusedUIDService,
  2360  			InputID:            "foo",
  2361  			Input:              updateInput,
  2362  			ExpectedErrMessage: testErr.Error(),
  2363  		},
  2364  		{
  2365  			Name:              "Should return error while creating webhook",
  2366  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2367  			AppRepoFn: func() *automock.ApplicationRepository {
  2368  				repo := &automock.ApplicationRepository{}
  2369  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2370  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2371  				repo.On("Exists", ctx, tnt, id).Return(true, nil).Twice()
  2372  				return repo
  2373  			},
  2374  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2375  				repo := &automock.IntegrationSystemRepository{}
  2376  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2377  				return repo
  2378  			},
  2379  			LabelSvcFn: func() *automock.LabelService {
  2380  				svc := &automock.LabelService{}
  2381  				svc.On("UpsertLabel", ctx, tnt, intSysLabel).Return(nil).Once()
  2382  				svc.On("UpsertLabel", ctx, tnt, nameLabel).Return(nil).Once()
  2383  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "applicationType").Return(appTypeLabel, nil).Once()
  2384  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "ppmsProductVersionId").Return(ppmsVersionIDLabel, nil).Once()
  2385  				return svc
  2386  			},
  2387  			WebhookRepoFn: func() *automock.WebhookRepository {
  2388  				webhookRepo := &automock.WebhookRepository{}
  2389  				webhookRepo.On("ListByReferenceObjectID", ctx, tnt, id, model.ApplicationWebhookReference).Return(nil, testErr)
  2390  				return webhookRepo
  2391  			},
  2392  			ORDWebhookMapping:  ordWebhookMapping,
  2393  			UIDServiceFn:       UnusedUIDService,
  2394  			InputID:            "foo",
  2395  			Input:              updateInput,
  2396  			ExpectedErrMessage: testErr.Error(),
  2397  		},
  2398  		{
  2399  			Name:              "Not matching ord mapping configuration",
  2400  			AppNameNormalizer: &normalizer.DefaultNormalizator{},
  2401  			AppRepoFn: func() *automock.ApplicationRepository {
  2402  				repo := &automock.ApplicationRepository{}
  2403  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2404  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2405  				repo.On("Exists", ctx, tnt, id).Return(true, nil).Twice()
  2406  				return repo
  2407  			},
  2408  			IntSysRepoFn: func() *automock.IntegrationSystemRepository {
  2409  				repo := &automock.IntegrationSystemRepository{}
  2410  				repo.On("Exists", ctx, intSysID).Return(true, nil).Once()
  2411  				return repo
  2412  			},
  2413  			LabelSvcFn: func() *automock.LabelService {
  2414  				svc := &automock.LabelService{}
  2415  				svc.On("UpsertLabel", ctx, tnt, intSysLabel).Return(nil).Once()
  2416  				svc.On("UpsertLabel", ctx, tnt, nameLabel).Return(nil).Once()
  2417  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "applicationType").Return(appTypeLabel, nil).Once()
  2418  				svc.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, id, "ppmsProductVersionId").Return(ppmsVersionIDLabel, nil).Once()
  2419  				return svc
  2420  			},
  2421  			WebhookRepoFn: UnusedWebhookRepository,
  2422  			ORDWebhookMapping: []application.ORDWebhookMapping{
  2423  				{
  2424  					Type:                "test-app-not-match",
  2425  					PpmsProductVersions: []string{"1"},
  2426  				},
  2427  			},
  2428  			UIDServiceFn:       UnusedUIDService,
  2429  			InputID:            "foo",
  2430  			Input:              updateInput,
  2431  			ExpectedErrMessage: "",
  2432  		},
  2433  	}
  2434  
  2435  	for _, testCase := range testCases {
  2436  		t.Run(testCase.Name, func(t *testing.T) {
  2437  			resetModels()
  2438  			appNameNormalizer := testCase.AppNameNormalizer
  2439  			appRepo := testCase.AppRepoFn()
  2440  			intSysRepo := testCase.IntSysRepoFn()
  2441  			lblSvc := testCase.LabelSvcFn()
  2442  			webhookRepo := testCase.WebhookRepoFn()
  2443  			uidSvc := testCase.UIDServiceFn()
  2444  			svc := application.NewService(appNameNormalizer, nil, appRepo, webhookRepo, nil, nil, intSysRepo, lblSvc, nil, uidSvc, nil, "", testCase.ORDWebhookMapping)
  2445  			svc.SetTimestampGen(timestampGenFunc)
  2446  
  2447  			// WHEN
  2448  			err := svc.Update(ctx, testCase.InputID, testCase.Input)
  2449  
  2450  			// then
  2451  			if testCase.ExpectedErrMessage == "" {
  2452  				require.NoError(t, err)
  2453  			} else {
  2454  				require.Error(t, err)
  2455  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  2456  			}
  2457  
  2458  			mock.AssertExpectationsForObjects(t, uidSvc, webhookRepo, appRepo, intSysRepo, lblSvc)
  2459  		})
  2460  	}
  2461  }
  2462  
  2463  func TestService_UpdateBaseURL(t *testing.T) {
  2464  	// GIVEN
  2465  	testErr := errors.New("Test error")
  2466  	ctxErr := errors.New("while loading tenant from context: cannot read tenant from context")
  2467  
  2468  	id := "foo"
  2469  	tnt := "tenant"
  2470  	externalTnt := "external-tnt"
  2471  	conditionTimestamp := time.Now()
  2472  	targetURL := "http://compass.kyma.local/api/event?myEvent=true"
  2473  
  2474  	var applicationModelBefore *model.Application
  2475  	var applicationModelAfter *model.Application
  2476  
  2477  	ctx := context.TODO()
  2478  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  2479  
  2480  	resetModels := func() {
  2481  		appName := "initial"
  2482  		description := "description"
  2483  		updatedBaseURL := "http://compass.kyma.local"
  2484  		url := "url.com"
  2485  		applicationModelBefore = fixModelApplicationWithAllUpdatableFields(id, appName, description, url, nil, nil, model.ApplicationStatusConditionConnected, conditionTimestamp)
  2486  		applicationModelAfter = fixModelApplicationWithAllUpdatableFields(id, appName, description, url, &updatedBaseURL, nil, model.ApplicationStatusConditionConnected, conditionTimestamp)
  2487  	}
  2488  
  2489  	resetModels()
  2490  
  2491  	testCases := []struct {
  2492  		Name               string
  2493  		AppRepoFn          func() *automock.ApplicationRepository
  2494  		Input              model.ApplicationUpdateInput
  2495  		InputID            string
  2496  		TargetURL          string
  2497  		Context            context.Context
  2498  		ExpectedErrMessage string
  2499  	}{
  2500  		{
  2501  			Name: "Success",
  2502  			AppRepoFn: func() *automock.ApplicationRepository {
  2503  				repo := &automock.ApplicationRepository{}
  2504  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2505  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(nil).Once()
  2506  				return repo
  2507  			},
  2508  			InputID:            id,
  2509  			TargetURL:          targetURL,
  2510  			Context:            ctx,
  2511  			ExpectedErrMessage: "",
  2512  		},
  2513  		{
  2514  			Name: "Returns error when application update failed",
  2515  			AppRepoFn: func() *automock.ApplicationRepository {
  2516  				repo := &automock.ApplicationRepository{}
  2517  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelBefore, nil).Once()
  2518  				repo.On("Update", ctx, tnt, applicationModelAfter).Return(testErr).Once()
  2519  				return repo
  2520  			},
  2521  			InputID:            id,
  2522  			TargetURL:          targetURL,
  2523  			Context:            ctx,
  2524  			ExpectedErrMessage: testErr.Error(),
  2525  		},
  2526  		{
  2527  			Name: "Returns error when application retrieval failed",
  2528  			AppRepoFn: func() *automock.ApplicationRepository {
  2529  				repo := &automock.ApplicationRepository{}
  2530  				repo.On("GetByID", ctx, tnt, id).Return(nil, testErr).Once()
  2531  				repo.AssertNotCalled(t, "Update")
  2532  				return repo
  2533  			},
  2534  			InputID:            id,
  2535  			TargetURL:          targetURL,
  2536  			Context:            ctx,
  2537  			ExpectedErrMessage: testErr.Error(),
  2538  		},
  2539  		{
  2540  			Name: "Returns error when tenant is not in the context",
  2541  			AppRepoFn: func() *automock.ApplicationRepository {
  2542  				repo := &automock.ApplicationRepository{}
  2543  				repo.AssertNotCalled(t, "Update")
  2544  				repo.AssertNotCalled(t, "GetByID")
  2545  
  2546  				return repo
  2547  			},
  2548  			InputID:            id,
  2549  			TargetURL:          targetURL,
  2550  			Context:            context.Background(),
  2551  			ExpectedErrMessage: ctxErr.Error(),
  2552  		},
  2553  		{
  2554  			Name: "Does not update Application when BaseURL is already set",
  2555  			AppRepoFn: func() *automock.ApplicationRepository {
  2556  				repo := &automock.ApplicationRepository{}
  2557  				repo.AssertNotCalled(t, "Update")
  2558  				repo.On("GetByID", ctx, tnt, id).Return(applicationModelAfter, nil).Once()
  2559  
  2560  				return repo
  2561  			},
  2562  			InputID:            id,
  2563  			TargetURL:          targetURL,
  2564  			Context:            ctx,
  2565  			ExpectedErrMessage: "",
  2566  		},
  2567  	}
  2568  
  2569  	for _, testCase := range testCases {
  2570  		t.Run(testCase.Name, func(t *testing.T) {
  2571  			resetModels()
  2572  			appRepo := testCase.AppRepoFn()
  2573  			svc := application.NewService(nil, nil, appRepo, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  2574  
  2575  			// WHEN
  2576  			err := svc.UpdateBaseURL(testCase.Context, testCase.InputID, testCase.TargetURL)
  2577  
  2578  			// then
  2579  			if testCase.ExpectedErrMessage == "" {
  2580  				require.NoError(t, err)
  2581  			} else {
  2582  				require.Error(t, err)
  2583  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  2584  			}
  2585  
  2586  			appRepo.AssertExpectations(t)
  2587  		})
  2588  	}
  2589  }
  2590  
  2591  func TestService_Delete(t *testing.T) {
  2592  	// GIVEN
  2593  	testErr := errors.New("Test error")
  2594  	id := "foo"
  2595  	desc := "Lorem ipsum"
  2596  	tnt := "tenant"
  2597  	externalTnt := "external-tnt"
  2598  
  2599  	scenarios := []interface{}{"Easter"}
  2600  	scenarioLabel := &model.Label{
  2601  		ID:    uuid.New().String(),
  2602  		Key:   model.ScenariosKey,
  2603  		Value: scenarios,
  2604  	}
  2605  
  2606  	emptyScenarioLabel := &model.Label{
  2607  		ID:    uuid.New().String(),
  2608  		Key:   model.ScenariosKey,
  2609  		Value: []interface{}{},
  2610  	}
  2611  
  2612  	applicationModel := &model.Application{
  2613  		Name:        "foo",
  2614  		Description: &desc,
  2615  		BaseEntity:  &model.BaseEntity{ID: id},
  2616  	}
  2617  
  2618  	ctx := context.TODO()
  2619  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  2620  
  2621  	testCases := []struct {
  2622  		Name               string
  2623  		AppRepoFn          func() *automock.ApplicationRepository
  2624  		LabelRepoFn        func() *automock.LabelRepository
  2625  		Input              model.ApplicationRegisterInput
  2626  		InputID            string
  2627  		ExpectedErrMessage string
  2628  	}{
  2629  		{
  2630  			Name: "Success",
  2631  			AppRepoFn: func() *automock.ApplicationRepository {
  2632  				repo := &automock.ApplicationRepository{}
  2633  				repo.On("Delete", ctx, tnt, applicationModel.ID).Return(nil).Once()
  2634  				repo.On("Exists", ctx, tnt, applicationModel.ID).Return(true, nil).Once()
  2635  				return repo
  2636  			},
  2637  			LabelRepoFn: func() *automock.LabelRepository {
  2638  				repo := &automock.LabelRepository{}
  2639  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(emptyScenarioLabel, nil).Once()
  2640  				return repo
  2641  			},
  2642  			InputID:            id,
  2643  			ExpectedErrMessage: "",
  2644  		},
  2645  		{
  2646  			Name: "Return error when application is part of a scenario",
  2647  			AppRepoFn: func() *automock.ApplicationRepository {
  2648  				repo := &automock.ApplicationRepository{}
  2649  				repo.AssertNotCalled(t, "Delete")
  2650  				repo.On("Exists", ctx, tnt, applicationModel.ID).Return(true, nil).Once()
  2651  				repo.On("GetByID", ctx, tnt, applicationModel.ID).Return(applicationModel, nil).Once()
  2652  				return repo
  2653  			},
  2654  			LabelRepoFn: func() *automock.LabelRepository {
  2655  				repo := &automock.LabelRepository{}
  2656  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(scenarioLabel, nil).Once()
  2657  				return repo
  2658  			},
  2659  			InputID:            id,
  2660  			ExpectedErrMessage: "System foo is part of the following formations : Easter",
  2661  		},
  2662  		{
  2663  			Name: "Return error when fails to get application by ID",
  2664  			AppRepoFn: func() *automock.ApplicationRepository {
  2665  				repo := &automock.ApplicationRepository{}
  2666  				repo.AssertNotCalled(t, "Delete")
  2667  				repo.On("Exists", ctx, tnt, applicationModel.ID).Return(true, nil).Once()
  2668  				repo.On("GetByID", ctx, tnt, applicationModel.ID).Return(nil, testErr).Once()
  2669  				return repo
  2670  			},
  2671  			LabelRepoFn: func() *automock.LabelRepository {
  2672  				repo := &automock.LabelRepository{}
  2673  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(scenarioLabel, nil).Once()
  2674  				return repo
  2675  			},
  2676  			InputID:            id,
  2677  			ExpectedErrMessage: testErr.Error(),
  2678  		},
  2679  		{
  2680  			Name: "Returns error when application deletion failed",
  2681  			AppRepoFn: func() *automock.ApplicationRepository {
  2682  				repo := &automock.ApplicationRepository{}
  2683  				repo.On("Delete", ctx, tnt, applicationModel.ID).Return(testErr).Once()
  2684  				repo.On("Exists", ctx, tnt, applicationModel.ID).Return(true, nil).Once()
  2685  				return repo
  2686  			},
  2687  			LabelRepoFn: func() *automock.LabelRepository {
  2688  				repo := &automock.LabelRepository{}
  2689  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(emptyScenarioLabel, nil).Once()
  2690  				return repo
  2691  			},
  2692  			InputID:            id,
  2693  			ExpectedErrMessage: testErr.Error(),
  2694  		},
  2695  	}
  2696  
  2697  	for _, testCase := range testCases {
  2698  		t.Run(testCase.Name, func(t *testing.T) {
  2699  			appRepo := testCase.AppRepoFn()
  2700  			labelRepo := testCase.LabelRepoFn()
  2701  			svc := application.NewService(nil, nil, appRepo, nil, nil, labelRepo, nil, nil, nil, nil, nil, "", nil)
  2702  
  2703  			// WHEN
  2704  			err := svc.Delete(ctx, testCase.InputID)
  2705  
  2706  			// then
  2707  			if testCase.ExpectedErrMessage == "" {
  2708  				require.NoError(t, err)
  2709  			} else {
  2710  				require.Error(t, err)
  2711  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  2712  			}
  2713  
  2714  			mock.AssertExpectationsForObjects(t, appRepo, labelRepo)
  2715  		})
  2716  	}
  2717  }
  2718  
  2719  func TestService_Unpair(t *testing.T) {
  2720  	// GIVEN
  2721  	testErr := errors.New("Test error")
  2722  	formationAndRuntimeError := errors.New("The operation is not allowed [reason=System foo is still used and cannot be deleted. Unassign the system from the following formations first: Easter. Then, unassign the system from the following runtimes, too: test-runtime]")
  2723  	id := "foo"
  2724  	desc := "Lorem ipsum"
  2725  	tnt := "tenant"
  2726  	externalTnt := "external-tnt"
  2727  
  2728  	scenarios := []interface{}{"Easter"}
  2729  	scenarioLabel := &model.Label{
  2730  		ID:    uuid.New().String(),
  2731  		Key:   model.ScenariosKey,
  2732  		Value: scenarios,
  2733  	}
  2734  
  2735  	emptyScenarioLabel := &model.Label{
  2736  		ID:    uuid.New().String(),
  2737  		Key:   model.ScenariosKey,
  2738  		Value: []interface{}{},
  2739  	}
  2740  
  2741  	timestamp := time.Now()
  2742  
  2743  	applicationModel := &model.Application{
  2744  		Name:        "foo",
  2745  		Description: &desc,
  2746  		Status: &model.ApplicationStatus{
  2747  			Condition: model.ApplicationStatusConditionConnected,
  2748  			Timestamp: timestamp,
  2749  		},
  2750  		BaseEntity: &model.BaseEntity{ID: id},
  2751  	}
  2752  
  2753  	applicationModelWithInitialStatus := &model.Application{
  2754  		Name:        "foo",
  2755  		Description: &desc,
  2756  		Status: &model.ApplicationStatus{
  2757  			Condition: model.ApplicationStatusConditionInitial,
  2758  			Timestamp: timestamp,
  2759  		},
  2760  		BaseEntity: &model.BaseEntity{ID: id},
  2761  	}
  2762  
  2763  	runtimeModel := &model.Runtime{
  2764  		Name: "test-runtime",
  2765  	}
  2766  
  2767  	ctx := context.Background()
  2768  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  2769  
  2770  	testCases := []struct {
  2771  		Name               string
  2772  		AppRepoFn          func() *automock.ApplicationRepository
  2773  		LabelRepoFn        func() *automock.LabelRepository
  2774  		RuntimeRepoFn      func() *automock.RuntimeRepository
  2775  		Input              model.ApplicationRegisterInput
  2776  		ContextFn          func() context.Context
  2777  		InputID            string
  2778  		ExpectedErrMessage string
  2779  	}{
  2780  		{
  2781  			Name: "Success",
  2782  			AppRepoFn: func() *automock.ApplicationRepository {
  2783  				repo := &automock.ApplicationRepository{}
  2784  				repo.On("Update", ctx, tnt, applicationModelWithInitialStatus).Return(nil).Once()
  2785  				repo.On("Exists", ctx, tnt, applicationModelWithInitialStatus.ID).Return(true, nil).Once()
  2786  				repo.On("GetByID", ctx, tnt, applicationModelWithInitialStatus.ID).Return(applicationModelWithInitialStatus, nil).Once()
  2787  				return repo
  2788  			},
  2789  			LabelRepoFn: func() *automock.LabelRepository {
  2790  				repo := &automock.LabelRepository{}
  2791  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(emptyScenarioLabel, nil)
  2792  				return repo
  2793  			},
  2794  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2795  				repo := &automock.RuntimeRepository{}
  2796  				repo.AssertNotCalled(t, "ListAll")
  2797  				return repo
  2798  			},
  2799  			ContextFn: func() context.Context {
  2800  				ctx := context.Background()
  2801  
  2802  				return ctx
  2803  			},
  2804  			InputID: id,
  2805  		},
  2806  		{
  2807  			Name: "Success when application is part of a scenario but not with runtime",
  2808  			AppRepoFn: func() *automock.ApplicationRepository {
  2809  				repo := &automock.ApplicationRepository{}
  2810  				repo.On("Update", ctx, tnt, applicationModel).Return(nil).Once()
  2811  				repo.On("Exists", ctx, tnt, applicationModel.ID).Return(true, nil).Once()
  2812  				repo.On("GetByID", ctx, tnt, applicationModel.ID).Return(applicationModel, nil).Once()
  2813  				return repo
  2814  			},
  2815  			LabelRepoFn: func() *automock.LabelRepository {
  2816  				repo := &automock.LabelRepository{}
  2817  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(scenarioLabel, nil)
  2818  				return repo
  2819  			},
  2820  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2821  				repo := &automock.RuntimeRepository{}
  2822  				repo.On("ListAll", ctx, tnt, mock.Anything).Return(scenarioLabel).Return([]*model.Runtime{}, nil)
  2823  				return repo
  2824  			},
  2825  			ContextFn: func() context.Context {
  2826  				ctx := context.Background()
  2827  
  2828  				return ctx
  2829  			},
  2830  			InputID: id,
  2831  		},
  2832  		{
  2833  			Name: "Success when operation type is SYNC and sets the application status to INITIAL",
  2834  			AppRepoFn: func() *automock.ApplicationRepository {
  2835  				repo := &automock.ApplicationRepository{}
  2836  				repo.On("Update", mock.Anything, tnt, applicationModelWithInitialStatus).Return(nil).Once()
  2837  				repo.On("Exists", ctx, tnt, applicationModel.ID).Return(true, nil).Once()
  2838  				repo.On("GetByID", ctx, tnt, applicationModel.ID).Return(applicationModel, nil).Once()
  2839  				return repo
  2840  			},
  2841  			LabelRepoFn: func() *automock.LabelRepository {
  2842  				repo := &automock.LabelRepository{}
  2843  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(scenarioLabel, nil)
  2844  				return repo
  2845  			},
  2846  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2847  				repo := &automock.RuntimeRepository{}
  2848  				repo.On("ListAll", ctx, tnt, mock.Anything).Return(scenarioLabel).Return([]*model.Runtime{}, nil)
  2849  				return repo
  2850  			},
  2851  			InputID: id,
  2852  			ContextFn: func() context.Context {
  2853  				backgroundCtx := context.Background()
  2854  				return backgroundCtx
  2855  			},
  2856  		},
  2857  		{
  2858  			Name: "Success when operation type is ASYNC and does not change the application status",
  2859  			AppRepoFn: func() *automock.ApplicationRepository {
  2860  				repo := &automock.ApplicationRepository{}
  2861  				repo.On("Update", mock.Anything, tnt, applicationModel).Return(nil).Once()
  2862  				repo.On("Exists", mock.Anything, tnt, applicationModel.ID).Return(true, nil).Once()
  2863  				repo.On("GetByID", mock.Anything, tnt, applicationModel.ID).Return(applicationModel, nil).Once()
  2864  				return repo
  2865  			},
  2866  			LabelRepoFn: func() *automock.LabelRepository {
  2867  				repo := &automock.LabelRepository{}
  2868  				repo.On("GetByKey", mock.Anything, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(scenarioLabel, nil)
  2869  				return repo
  2870  			},
  2871  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2872  				repo := &automock.RuntimeRepository{}
  2873  				repo.On("ListAll", mock.Anything, tnt, mock.Anything).Return(scenarioLabel).Return([]*model.Runtime{}, nil)
  2874  				return repo
  2875  			},
  2876  			InputID: id,
  2877  			ContextFn: func() context.Context {
  2878  				backgroundCtx := context.Background()
  2879  				backgroundCtx = operation.SaveModeToContext(backgroundCtx, graphql.OperationModeAsync)
  2880  				return backgroundCtx
  2881  			},
  2882  		},
  2883  		{
  2884  			Name: "Returns error when application fetch failed",
  2885  			AppRepoFn: func() *automock.ApplicationRepository {
  2886  				repo := &automock.ApplicationRepository{}
  2887  				repo.On("GetByID", ctx, tnt, applicationModel.ID).Return(nil, testErr).Once()
  2888  				repo.On("Exists", ctx, tnt, applicationModel.ID).Return(true, nil).Once()
  2889  				repo.AssertNotCalled(t, "Update")
  2890  				return repo
  2891  			},
  2892  			LabelRepoFn: func() *automock.LabelRepository {
  2893  				repo := &automock.LabelRepository{}
  2894  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(emptyScenarioLabel, nil)
  2895  				return repo
  2896  			},
  2897  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2898  				repo := &automock.RuntimeRepository{}
  2899  				repo.AssertNotCalled(t, "ListAll")
  2900  				return repo
  2901  			},
  2902  			ContextFn: func() context.Context {
  2903  				ctx := context.Background()
  2904  
  2905  				return ctx
  2906  			},
  2907  			InputID:            id,
  2908  			ExpectedErrMessage: testErr.Error(),
  2909  		},
  2910  		{
  2911  			Name: "Returns error when application is part of a scenario with runtime",
  2912  			AppRepoFn: func() *automock.ApplicationRepository {
  2913  				repo := &automock.ApplicationRepository{}
  2914  				repo.AssertNotCalled(t, "Delete")
  2915  				repo.On("Exists", ctx, tnt, applicationModel.ID).Return(true, nil).Once()
  2916  				repo.On("GetByID", ctx, tnt, applicationModel.ID).Return(applicationModel, nil).Once()
  2917  				repo.AssertNotCalled(t, "Update")
  2918  				return repo
  2919  			},
  2920  			LabelRepoFn: func() *automock.LabelRepository {
  2921  				repo := &automock.LabelRepository{}
  2922  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(scenarioLabel, nil)
  2923  				return repo
  2924  			},
  2925  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2926  				repo := &automock.RuntimeRepository{}
  2927  				repo.On("ListAll", ctx, tnt, mock.Anything).Return(scenarioLabel).Return([]*model.Runtime{runtimeModel}, nil)
  2928  				return repo
  2929  			},
  2930  			ContextFn: func() context.Context {
  2931  				ctx := context.Background()
  2932  
  2933  				return ctx
  2934  			},
  2935  			InputID:            id,
  2936  			ExpectedErrMessage: formationAndRuntimeError.Error(),
  2937  		},
  2938  		{
  2939  			Name: "Returns error when update fails",
  2940  			AppRepoFn: func() *automock.ApplicationRepository {
  2941  				repo := &automock.ApplicationRepository{}
  2942  				repo.AssertNotCalled(t, "Delete")
  2943  				repo.On("Update", ctx, tnt, applicationModel).Return(testErr).Once()
  2944  				repo.On("Exists", ctx, tnt, applicationModel.ID).Return(true, nil).Once()
  2945  				repo.On("GetByID", ctx, tnt, applicationModel.ID).Return(applicationModel, nil).Once()
  2946  				return repo
  2947  			},
  2948  			LabelRepoFn: func() *automock.LabelRepository {
  2949  				repo := &automock.LabelRepository{}
  2950  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationModel.ID, model.ScenariosKey).Return(emptyScenarioLabel, nil)
  2951  				return repo
  2952  			},
  2953  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  2954  				repo := &automock.RuntimeRepository{}
  2955  				repo.AssertNotCalled(t, "ListAll")
  2956  				return repo
  2957  			},
  2958  			ContextFn: func() context.Context {
  2959  				ctx := context.Background()
  2960  
  2961  				return ctx
  2962  			},
  2963  			InputID:            id,
  2964  			ExpectedErrMessage: testErr.Error(),
  2965  		},
  2966  	}
  2967  
  2968  	for _, testCase := range testCases {
  2969  		t.Run(testCase.Name, func(t *testing.T) {
  2970  			appRepo := testCase.AppRepoFn()
  2971  			labelRepo := testCase.LabelRepoFn()
  2972  			runtimeRepo := testCase.RuntimeRepoFn()
  2973  			ctx := testCase.ContextFn()
  2974  			ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  2975  			svc := application.NewService(nil, nil, appRepo, nil, runtimeRepo, labelRepo, nil, nil, nil, nil, nil, "", nil)
  2976  			svc.SetTimestampGen(func() time.Time { return timestamp })
  2977  			// WHEN
  2978  			err := svc.Unpair(ctx, testCase.InputID)
  2979  
  2980  			// then
  2981  			if testCase.ExpectedErrMessage == "" {
  2982  				require.NoError(t, err)
  2983  			} else {
  2984  				require.Error(t, err)
  2985  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  2986  			}
  2987  
  2988  			mock.AssertExpectationsForObjects(t, appRepo, labelRepo, runtimeRepo)
  2989  		})
  2990  	}
  2991  }
  2992  
  2993  func TestService_Merge(t *testing.T) {
  2994  	// GIVEN
  2995  	testErr := errors.New("Test error")
  2996  	destID := "foo"
  2997  	srcID := "bar"
  2998  	tnt := "tenant"
  2999  	externalTnt := "external-tnt"
  3000  	baseURL := "http://localhost.com"
  3001  	templateID := "12346789"
  3002  	otherTemplateID := "qwerty"
  3003  	destName := "dest app"
  3004  	srcName := "src app"
  3005  	srcDescription := "Long src description"
  3006  	selfRegDistLabelKey := "subscriptionProviderId"
  3007  
  3008  	labelKey1 := model.ScenariosKey
  3009  	labelKey2 := "managed"
  3010  	var labelValue1 []interface{}
  3011  	labelValue2 := []interface{}{"Easter", "Bunny"}
  3012  
  3013  	upsertLabelValues := make(map[string]interface{})
  3014  	upsertLabelValues[labelKey1] = []string{"Easter", "Bunny"}
  3015  	upsertLabelValues[labelKey2] = "true"
  3016  
  3017  	upsertLabelValuesWithManagedFalse := make(map[string]interface{})
  3018  	upsertLabelValuesWithManagedFalse[labelKey1] = []string{"Easter", "Bunny"}
  3019  	upsertLabelValuesWithManagedFalse[labelKey2] = "false"
  3020  
  3021  	srcAppLabels := fixApplicationLabels(srcID, labelKey1, labelKey2, labelValue1, "true")
  3022  	destAppLabels := fixApplicationLabels(srcID, labelKey1, labelKey2, labelValue2, "false")
  3023  	srcAppLabelsWithFalseManaged := fixApplicationLabels(srcID, labelKey1, labelKey2, labelValue1, "false")
  3024  	appTemplateLabelsWithSelfRegDistLabelKey := map[string]*model.Label{
  3025  		selfRegDistLabelKey: {
  3026  			ID:         "abc",
  3027  			Tenant:     str.Ptr(tnt),
  3028  			Key:        selfRegDistLabelKey,
  3029  			Value:      labelValue1,
  3030  			ObjectID:   templateID,
  3031  			ObjectType: model.AppTemplateLabelableObject,
  3032  		},
  3033  	}
  3034  
  3035  	srcModel := fixDetailedModelApplication(t, srcID, tnt, srcName, srcDescription)
  3036  	srcModel.ApplicationTemplateID = &templateID
  3037  	srcModel.Status.Timestamp = time.Time{}
  3038  
  3039  	destModel := fixModelApplication(destID, tnt, destName, "")
  3040  	destModel.ApplicationTemplateID = &templateID
  3041  	destModel.BaseURL = srcModel.BaseURL
  3042  	destModel.Status.Timestamp = time.Time{}
  3043  
  3044  	mergedDestModel := fixDetailedModelApplication(t, destID, tnt, destName, srcDescription)
  3045  	mergedDestModel.ApplicationTemplateID = &templateID
  3046  	mergedDestModel.Status.Timestamp = time.Time{}
  3047  
  3048  	srcModelWithoutBaseURL := fixDetailedModelApplication(t, srcID, tnt, srcName, srcDescription)
  3049  	srcModelWithoutBaseURL.BaseURL = nil
  3050  
  3051  	srcModelWithDifferentBaseURL := fixDetailedModelApplication(t, srcID, tnt, srcName, srcDescription)
  3052  	srcModelWithDifferentBaseURL.BaseURL = &baseURL
  3053  
  3054  	srcModelWithDifferentTemplateID := fixDetailedModelApplication(t, srcID, tnt, srcName, srcDescription)
  3055  	srcModelWithDifferentTemplateID.ApplicationTemplateID = &otherTemplateID
  3056  
  3057  	srcModelConnected := fixDetailedModelApplication(t, srcID, tnt, srcName, srcDescription)
  3058  	srcModelConnected.Status.Condition = model.ApplicationStatusConditionConnected
  3059  	srcModelConnected.ApplicationTemplateID = &templateID
  3060  
  3061  	ctx := context.TODO()
  3062  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  3063  
  3064  	testCases := []struct {
  3065  		Name                           string
  3066  		AppRepoFn                      func() *automock.ApplicationRepository
  3067  		LabelRepoFn                    func() *automock.LabelRepository
  3068  		LabelUpsertSvcFn               func() *automock.LabelService
  3069  		ExpectedDestinationApplication *model.Application
  3070  		Ctx                            context.Context
  3071  		SourceID                       string
  3072  		DestinationID                  string
  3073  		ExpectedErrMessage             string
  3074  	}{
  3075  		{
  3076  			Name: "Success",
  3077  			AppRepoFn: func() *automock.ApplicationRepository {
  3078  				repo := &automock.ApplicationRepository{}
  3079  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3080  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3081  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3082  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Twice()
  3083  				repo.On("Update", ctx, tnt, destModel).Return(nil).Once()
  3084  				repo.On("Delete", ctx, tnt, srcModel.ID).Return(nil).Once()
  3085  				return repo
  3086  			},
  3087  			LabelRepoFn: func() *automock.LabelRepository {
  3088  				repo := &automock.LabelRepository{}
  3089  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3090  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabels, nil)
  3091  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3092  				repo.On("ListForObject", ctx, tnt, model.AppTemplateLabelableObject, *srcModel.ApplicationTemplateID).Return(map[string]*model.Label{}, nil)
  3093  				return repo
  3094  			},
  3095  			LabelUpsertSvcFn: func() *automock.LabelService {
  3096  				svc := &automock.LabelService{}
  3097  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, destModel.ID, upsertLabelValues).Return(nil)
  3098  				return svc
  3099  			},
  3100  			Ctx:                            ctx,
  3101  			DestinationID:                  destID,
  3102  			SourceID:                       srcID,
  3103  			ExpectedDestinationApplication: mergedDestModel,
  3104  			ExpectedErrMessage:             "",
  3105  		},
  3106  		{
  3107  			Name: "Success with managed \"false\" label when both labels are \"false\"",
  3108  			AppRepoFn: func() *automock.ApplicationRepository {
  3109  				repo := &automock.ApplicationRepository{}
  3110  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3111  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3112  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3113  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Twice()
  3114  				repo.On("Update", ctx, tnt, destModel).Return(nil).Once()
  3115  				repo.On("Delete", ctx, tnt, srcModel.ID).Return(nil).Once()
  3116  				return repo
  3117  			},
  3118  			LabelRepoFn: func() *automock.LabelRepository {
  3119  				repo := &automock.LabelRepository{}
  3120  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3121  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabelsWithFalseManaged, nil)
  3122  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3123  				repo.On("ListForObject", ctx, tnt, model.AppTemplateLabelableObject, *srcModel.ApplicationTemplateID).Return(map[string]*model.Label{}, nil)
  3124  				return repo
  3125  			},
  3126  			LabelUpsertSvcFn: func() *automock.LabelService {
  3127  				svc := &automock.LabelService{}
  3128  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, destModel.ID, upsertLabelValuesWithManagedFalse).Return(nil)
  3129  				return svc
  3130  			},
  3131  			Ctx:                            ctx,
  3132  			DestinationID:                  destID,
  3133  			SourceID:                       srcID,
  3134  			ExpectedDestinationApplication: mergedDestModel,
  3135  			ExpectedErrMessage:             "",
  3136  		},
  3137  		{
  3138  			Name: "Error when tenant is not in context",
  3139  			AppRepoFn: func() *automock.ApplicationRepository {
  3140  				repo := &automock.ApplicationRepository{}
  3141  				repo.AssertNotCalled(t, "GetByID")
  3142  				repo.AssertNotCalled(t, "Exists")
  3143  				repo.AssertNotCalled(t, "Update")
  3144  				repo.AssertNotCalled(t, "Delete")
  3145  				return repo
  3146  			},
  3147  			LabelRepoFn: func() *automock.LabelRepository {
  3148  				repo := &automock.LabelRepository{}
  3149  				repo.AssertNotCalled(t, "GetByKey")
  3150  				repo.AssertNotCalled(t, "ListForObject")
  3151  				return repo
  3152  			},
  3153  			LabelUpsertSvcFn: func() *automock.LabelService {
  3154  				svc := &automock.LabelService{}
  3155  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3156  				return svc
  3157  			},
  3158  			Ctx:                context.Background(),
  3159  			DestinationID:      destID,
  3160  			SourceID:           srcID,
  3161  			ExpectedErrMessage: "while loading tenant from context: cannot read tenant from context",
  3162  		},
  3163  		{
  3164  			Name: "Error when cannot get destination application",
  3165  			AppRepoFn: func() *automock.ApplicationRepository {
  3166  				repo := &automock.ApplicationRepository{}
  3167  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3168  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(nil, testErr).Once()
  3169  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Once()
  3170  				repo.AssertNotCalled(t, "Update")
  3171  				repo.AssertNotCalled(t, "Delete")
  3172  				return repo
  3173  			},
  3174  			LabelRepoFn: func() *automock.LabelRepository {
  3175  				repo := &automock.LabelRepository{}
  3176  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3177  				repo.AssertNotCalled(t, "ListForObject")
  3178  				return repo
  3179  			},
  3180  			LabelUpsertSvcFn: func() *automock.LabelService {
  3181  				svc := &automock.LabelService{}
  3182  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3183  				return svc
  3184  			},
  3185  			Ctx:                ctx,
  3186  			DestinationID:      destID,
  3187  			SourceID:           srcID,
  3188  			ExpectedErrMessage: testErr.Error(),
  3189  		},
  3190  		{
  3191  			Name: "Error when cannot get source application",
  3192  			AppRepoFn: func() *automock.ApplicationRepository {
  3193  				repo := &automock.ApplicationRepository{}
  3194  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(nil, testErr).Once()
  3195  				repo.AssertNotCalled(t, "Exists")
  3196  				repo.AssertNotCalled(t, "Update")
  3197  				repo.AssertNotCalled(t, "Delete")
  3198  				return repo
  3199  			},
  3200  			LabelRepoFn: func() *automock.LabelRepository {
  3201  				repo := &automock.LabelRepository{}
  3202  				repo.AssertNotCalled(t, "GetByKey")
  3203  				repo.AssertNotCalled(t, "ListForObject")
  3204  				return repo
  3205  			},
  3206  			LabelUpsertSvcFn: func() *automock.LabelService {
  3207  				svc := &automock.LabelService{}
  3208  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3209  				return svc
  3210  			},
  3211  			Ctx:                ctx,
  3212  			DestinationID:      destID,
  3213  			SourceID:           srcID,
  3214  			ExpectedErrMessage: testErr.Error(),
  3215  		},
  3216  		{
  3217  			Name: "Error when source app and destination app templates do not match",
  3218  			AppRepoFn: func() *automock.ApplicationRepository {
  3219  				repo := &automock.ApplicationRepository{}
  3220  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3221  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModelWithDifferentTemplateID, nil).Once()
  3222  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Once()
  3223  				repo.AssertNotCalled(t, "Update")
  3224  				repo.AssertNotCalled(t, "Delete")
  3225  				return repo
  3226  			},
  3227  			LabelRepoFn: func() *automock.LabelRepository {
  3228  				repo := &automock.LabelRepository{}
  3229  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3230  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabels, nil)
  3231  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3232  				repo.AssertNotCalled(t, "ListForObject")
  3233  				return repo
  3234  			},
  3235  			LabelUpsertSvcFn: func() *automock.LabelService {
  3236  				svc := &automock.LabelService{}
  3237  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3238  				return svc
  3239  			},
  3240  			Ctx:                ctx,
  3241  			DestinationID:      destID,
  3242  			SourceID:           srcID,
  3243  			ExpectedErrMessage: "Application templates are not the same. Destination app template: 12346789. Source app template: qwerty",
  3244  		},
  3245  		{
  3246  			Name: "Error when source app and destination app base url do not match",
  3247  			AppRepoFn: func() *automock.ApplicationRepository {
  3248  				repo := &automock.ApplicationRepository{}
  3249  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3250  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModelWithDifferentBaseURL, nil).Once()
  3251  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Once()
  3252  				repo.AssertNotCalled(t, "Update")
  3253  				repo.AssertNotCalled(t, "Delete")
  3254  				return repo
  3255  			},
  3256  			LabelRepoFn: func() *automock.LabelRepository {
  3257  				repo := &automock.LabelRepository{}
  3258  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3259  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabels, nil)
  3260  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3261  				repo.AssertNotCalled(t, "ListForObject")
  3262  				return repo
  3263  			},
  3264  			LabelUpsertSvcFn: func() *automock.LabelService {
  3265  				svc := &automock.LabelService{}
  3266  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3267  				return svc
  3268  			},
  3269  			Ctx:                ctx,
  3270  			DestinationID:      destID,
  3271  			SourceID:           srcID,
  3272  			ExpectedErrMessage: "BaseURL for applications foo and bar are not the same.",
  3273  		},
  3274  		{
  3275  			Name: "Error when source app is in CONNECTED status",
  3276  			AppRepoFn: func() *automock.ApplicationRepository {
  3277  				repo := &automock.ApplicationRepository{}
  3278  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3279  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModelConnected, nil).Once()
  3280  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Once()
  3281  				repo.AssertNotCalled(t, "Update")
  3282  				repo.AssertNotCalled(t, "Delete")
  3283  				return repo
  3284  			},
  3285  			LabelRepoFn: func() *automock.LabelRepository {
  3286  				repo := &automock.LabelRepository{}
  3287  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3288  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabels, nil)
  3289  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3290  				repo.On("ListForObject", ctx, tnt, model.AppTemplateLabelableObject, *srcModel.ApplicationTemplateID).Return(map[string]*model.Label{}, nil)
  3291  				return repo
  3292  			},
  3293  			LabelUpsertSvcFn: func() *automock.LabelService {
  3294  				svc := &automock.LabelService{}
  3295  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3296  				return svc
  3297  			},
  3298  			Ctx:                ctx,
  3299  			DestinationID:      destID,
  3300  			SourceID:           srcID,
  3301  			ExpectedErrMessage: "Cannot merge application with id bar, because it is in a CONNECTED status",
  3302  		},
  3303  		{
  3304  			Name: "Error when source deletion fails",
  3305  			AppRepoFn: func() *automock.ApplicationRepository {
  3306  				repo := &automock.ApplicationRepository{}
  3307  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3308  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3309  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Twice()
  3310  				repo.AssertNotCalled(t, "Update")
  3311  				repo.On("Delete", ctx, tnt, srcModel.ID).Return(testErr).Once()
  3312  				return repo
  3313  			},
  3314  			LabelRepoFn: func() *automock.LabelRepository {
  3315  				repo := &automock.LabelRepository{}
  3316  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3317  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabels, nil)
  3318  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3319  				repo.On("ListForObject", ctx, tnt, model.AppTemplateLabelableObject, *srcModel.ApplicationTemplateID).Return(map[string]*model.Label{}, nil)
  3320  				return repo
  3321  			},
  3322  			LabelUpsertSvcFn: func() *automock.LabelService {
  3323  				svc := &automock.LabelService{}
  3324  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3325  				return svc
  3326  			},
  3327  			Ctx:                ctx,
  3328  			DestinationID:      destID,
  3329  			SourceID:           srcID,
  3330  			ExpectedErrMessage: testErr.Error(),
  3331  		},
  3332  		{
  3333  			Name: "Error when destination app update fails",
  3334  			AppRepoFn: func() *automock.ApplicationRepository {
  3335  				repo := &automock.ApplicationRepository{}
  3336  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3337  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3338  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Twice()
  3339  				repo.On("Update", ctx, tnt, mergedDestModel).Return(testErr)
  3340  				repo.On("Delete", ctx, tnt, srcModel.ID).Return(nil).Once()
  3341  				return repo
  3342  			},
  3343  			LabelRepoFn: func() *automock.LabelRepository {
  3344  				repo := &automock.LabelRepository{}
  3345  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3346  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabels, nil)
  3347  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3348  				repo.On("ListForObject", ctx, tnt, model.AppTemplateLabelableObject, *srcModel.ApplicationTemplateID).Return(map[string]*model.Label{}, nil)
  3349  				return repo
  3350  			},
  3351  			LabelUpsertSvcFn: func() *automock.LabelService {
  3352  				svc := &automock.LabelService{}
  3353  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3354  				return svc
  3355  			},
  3356  			Ctx:                ctx,
  3357  			DestinationID:      destID,
  3358  			SourceID:           srcID,
  3359  			ExpectedErrMessage: testErr.Error(),
  3360  		},
  3361  		{
  3362  			Name: "Error when update labels fails",
  3363  			AppRepoFn: func() *automock.ApplicationRepository {
  3364  				repo := &automock.ApplicationRepository{}
  3365  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3366  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3367  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Twice()
  3368  				repo.On("Update", ctx, tnt, mergedDestModel).Return(nil)
  3369  				repo.On("Delete", ctx, tnt, srcModel.ID).Return(nil).Once()
  3370  				return repo
  3371  			},
  3372  			LabelRepoFn: func() *automock.LabelRepository {
  3373  				repo := &automock.LabelRepository{}
  3374  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3375  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabels, nil)
  3376  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3377  				repo.On("ListForObject", ctx, tnt, model.AppTemplateLabelableObject, *srcModel.ApplicationTemplateID).Return(map[string]*model.Label{}, nil)
  3378  				return repo
  3379  			},
  3380  			LabelUpsertSvcFn: func() *automock.LabelService {
  3381  				svc := &automock.LabelService{}
  3382  				svc.On("UpsertMultipleLabels", ctx, tnt, model.ApplicationLabelableObject, destModel.ID, upsertLabelValues).Return(testErr)
  3383  				return svc
  3384  			},
  3385  			Ctx:                ctx,
  3386  			DestinationID:      destID,
  3387  			SourceID:           srcID,
  3388  			ExpectedErrMessage: testErr.Error(),
  3389  		},
  3390  		{
  3391  			Name: "Error when app template has label subscriptionProviderId",
  3392  			AppRepoFn: func() *automock.ApplicationRepository {
  3393  				repo := &automock.ApplicationRepository{}
  3394  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3395  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3396  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Once()
  3397  				repo.AssertNotCalled(t, "Update")
  3398  				repo.AssertNotCalled(t, "Delete")
  3399  				return repo
  3400  			},
  3401  			LabelRepoFn: func() *automock.LabelRepository {
  3402  				repo := &automock.LabelRepository{}
  3403  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3404  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabels, nil)
  3405  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3406  				repo.On("ListForObject", ctx, tnt, model.AppTemplateLabelableObject, *srcModel.ApplicationTemplateID).Return(appTemplateLabelsWithSelfRegDistLabelKey, nil)
  3407  
  3408  				return repo
  3409  			},
  3410  			LabelUpsertSvcFn: func() *automock.LabelService {
  3411  				svc := &automock.LabelService{}
  3412  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3413  				return svc
  3414  			},
  3415  			Ctx:                ctx,
  3416  			DestinationID:      destID,
  3417  			SourceID:           srcID,
  3418  			ExpectedErrMessage: "app template: 12346789 has label subscriptionProviderId",
  3419  		},
  3420  		{
  3421  			Name: "Error when cannot get application template labels",
  3422  			AppRepoFn: func() *automock.ApplicationRepository {
  3423  				repo := &automock.ApplicationRepository{}
  3424  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3425  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3426  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Once()
  3427  				repo.AssertNotCalled(t, "Update")
  3428  				repo.AssertNotCalled(t, "Delete")
  3429  				return repo
  3430  			},
  3431  			LabelRepoFn: func() *automock.LabelRepository {
  3432  				repo := &automock.LabelRepository{}
  3433  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3434  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(srcAppLabels, nil)
  3435  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3436  				repo.On("ListForObject", ctx, tnt, model.AppTemplateLabelableObject, *srcModel.ApplicationTemplateID).Return(nil, testErr)
  3437  
  3438  				return repo
  3439  			},
  3440  			LabelUpsertSvcFn: func() *automock.LabelService {
  3441  				svc := &automock.LabelService{}
  3442  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3443  				return svc
  3444  			},
  3445  			Ctx:                ctx,
  3446  			DestinationID:      destID,
  3447  			SourceID:           srcID,
  3448  			ExpectedErrMessage: testErr.Error(),
  3449  		},
  3450  		{
  3451  			Name: "Error while checking if source app exists",
  3452  			AppRepoFn: func() *automock.ApplicationRepository {
  3453  				repo := &automock.ApplicationRepository{}
  3454  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3455  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(false, testErr).Once()
  3456  				repo.AssertNotCalled(t, "Update")
  3457  				repo.AssertNotCalled(t, "Delete")
  3458  				return repo
  3459  			},
  3460  			LabelRepoFn: UnusedLabelRepository,
  3461  			LabelUpsertSvcFn: func() *automock.LabelService {
  3462  				svc := &automock.LabelService{}
  3463  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3464  				return svc
  3465  			},
  3466  			Ctx:                ctx,
  3467  			DestinationID:      destID,
  3468  			SourceID:           srcID,
  3469  			ExpectedErrMessage: testErr.Error(),
  3470  		},
  3471  		{
  3472  			Name: "Error while listing source app labels",
  3473  			AppRepoFn: func() *automock.ApplicationRepository {
  3474  				repo := &automock.ApplicationRepository{}
  3475  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3476  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3477  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Once()
  3478  				repo.AssertNotCalled(t, "Update")
  3479  				repo.AssertNotCalled(t, "Delete")
  3480  				return repo
  3481  			},
  3482  			LabelRepoFn: func() *automock.LabelRepository {
  3483  				repo := &automock.LabelRepository{}
  3484  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3485  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID).Return(nil, testErr)
  3486  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(destAppLabels, nil)
  3487  				return repo
  3488  			},
  3489  			LabelUpsertSvcFn: func() *automock.LabelService {
  3490  				svc := &automock.LabelService{}
  3491  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3492  				return svc
  3493  			},
  3494  			Ctx:                ctx,
  3495  			DestinationID:      destID,
  3496  			SourceID:           srcID,
  3497  			ExpectedErrMessage: testErr.Error(),
  3498  		},
  3499  		{
  3500  			Name: "Error while listing destination app labels",
  3501  			AppRepoFn: func() *automock.ApplicationRepository {
  3502  				repo := &automock.ApplicationRepository{}
  3503  				repo.On("GetByID", ctx, tnt, destModel.ID).Return(destModel, nil).Once()
  3504  				repo.On("GetByID", ctx, tnt, srcModel.ID).Return(srcModel, nil).Once()
  3505  				repo.On("Exists", ctx, tnt, srcModel.ID).Return(true, nil).Once()
  3506  				repo.AssertNotCalled(t, "Update")
  3507  				repo.AssertNotCalled(t, "Delete")
  3508  				return repo
  3509  			},
  3510  			LabelRepoFn: func() *automock.LabelRepository {
  3511  				repo := &automock.LabelRepository{}
  3512  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, srcModel.ID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
  3513  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, destModel.ID).Return(nil, testErr)
  3514  
  3515  				return repo
  3516  			},
  3517  			LabelUpsertSvcFn: func() *automock.LabelService {
  3518  				svc := &automock.LabelService{}
  3519  				svc.AssertNotCalled(t, "UpsertMultipleLabels")
  3520  				return svc
  3521  			},
  3522  			Ctx:                ctx,
  3523  			DestinationID:      destID,
  3524  			SourceID:           srcID,
  3525  			ExpectedErrMessage: testErr.Error(),
  3526  		},
  3527  	}
  3528  
  3529  	for _, testCase := range testCases {
  3530  		t.Run(testCase.Name, func(t *testing.T) {
  3531  			appRepo := testCase.AppRepoFn()
  3532  			labelRepo := testCase.LabelRepoFn()
  3533  			labelUpserSvc := testCase.LabelUpsertSvcFn()
  3534  			svc := application.NewService(nil, nil, appRepo, nil, nil, labelRepo, nil, labelUpserSvc, nil, nil, nil, selfRegDistLabelKey, nil)
  3535  
  3536  			// WHEN
  3537  			destApp, err := svc.Merge(testCase.Ctx, testCase.DestinationID, testCase.SourceID)
  3538  
  3539  			// then
  3540  			if testCase.ExpectedErrMessage == "" {
  3541  				require.NoError(t, err)
  3542  				assert.Equal(t, testCase.ExpectedDestinationApplication, destApp)
  3543  			} else {
  3544  				require.Error(t, err)
  3545  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  3546  			}
  3547  
  3548  			mock.AssertExpectationsForObjects(t, appRepo, labelRepo, labelUpserSvc)
  3549  		})
  3550  
  3551  		srcAppLabels = fixApplicationLabels(srcID, labelKey1, labelKey2, labelValue1, "true")
  3552  		destAppLabels = fixApplicationLabels(srcID, labelKey1, labelKey2, labelValue2, "false")
  3553  	}
  3554  }
  3555  
  3556  func TestService_Get(t *testing.T) {
  3557  	// GIVEN
  3558  	testErr := errors.New("Test error")
  3559  
  3560  	id := "foo"
  3561  
  3562  	desc := "Lorem ipsum"
  3563  
  3564  	applicationModel := &model.Application{
  3565  		Name:        "foo",
  3566  		Description: &desc,
  3567  		BaseEntity:  &model.BaseEntity{ID: "foo"},
  3568  	}
  3569  
  3570  	tnt := "tenant"
  3571  	externalTnt := "external-tnt"
  3572  
  3573  	ctx := context.TODO()
  3574  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  3575  
  3576  	testCases := []struct {
  3577  		Name                string
  3578  		RepositoryFn        func() *automock.ApplicationRepository
  3579  		InputID             string
  3580  		ExpectedApplication *model.Application
  3581  		ExpectedErrMessage  string
  3582  	}{
  3583  		{
  3584  			Name: "Success",
  3585  			RepositoryFn: func() *automock.ApplicationRepository {
  3586  				repo := &automock.ApplicationRepository{}
  3587  				repo.On("GetByID", ctx, tnt, id).Return(applicationModel, nil).Once()
  3588  				return repo
  3589  			},
  3590  			InputID:             id,
  3591  			ExpectedApplication: applicationModel,
  3592  			ExpectedErrMessage:  "",
  3593  		},
  3594  		{
  3595  			Name: "Returns error when application retrieval failed",
  3596  			RepositoryFn: func() *automock.ApplicationRepository {
  3597  				repo := &automock.ApplicationRepository{}
  3598  				repo.On("GetByID", ctx, tnt, id).Return(nil, testErr).Once()
  3599  				return repo
  3600  			},
  3601  			InputID:             id,
  3602  			ExpectedApplication: applicationModel,
  3603  			ExpectedErrMessage:  testErr.Error(),
  3604  		},
  3605  	}
  3606  
  3607  	for _, testCase := range testCases {
  3608  		t.Run(testCase.Name, func(t *testing.T) {
  3609  			repo := testCase.RepositoryFn()
  3610  
  3611  			svc := application.NewService(nil, nil, repo, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  3612  
  3613  			// WHEN
  3614  			app, err := svc.Get(ctx, testCase.InputID)
  3615  
  3616  			// then
  3617  			if testCase.ExpectedErrMessage == "" {
  3618  				require.NoError(t, err)
  3619  				assert.Equal(t, testCase.ExpectedApplication, app)
  3620  			} else {
  3621  				require.Error(t, err)
  3622  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  3623  			}
  3624  
  3625  			repo.AssertExpectations(t)
  3626  		})
  3627  	}
  3628  }
  3629  
  3630  func TestService_GetSystem(t *testing.T) {
  3631  	// GIVEN
  3632  	testErr := errors.New("test error")
  3633  
  3634  	tnt := "id"
  3635  	locationID := "loc_id"
  3636  	virtualHost := "vhost"
  3637  	filter := labelfilter.NewForKeyWithQuery("scc", fmt.Sprintf("{\"Host\":\"%s\",\"Subaccount\":\"%s\",\"LocationID\":\"%s\"}", virtualHost, tnt, locationID))
  3638  
  3639  	desc := "Lorem ipsum"
  3640  
  3641  	applicationModel := &model.Application{
  3642  		Name:        "foo",
  3643  		Description: &desc,
  3644  		BaseEntity:  &model.BaseEntity{ID: "foo"},
  3645  	}
  3646  
  3647  	externalTnt := "external-tnt"
  3648  
  3649  	ctx := context.TODO()
  3650  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  3651  
  3652  	testCases := []struct {
  3653  		Name                string
  3654  		Ctx                 context.Context
  3655  		RepositoryFn        func() *automock.ApplicationRepository
  3656  		ExpectedApplication *model.Application
  3657  		ExpectedErrMessage  string
  3658  	}{
  3659  		{
  3660  			Name: "Success",
  3661  			Ctx:  ctx,
  3662  			RepositoryFn: func() *automock.ApplicationRepository {
  3663  				repo := &automock.ApplicationRepository{}
  3664  				repo.On("GetByFilter", ctx, tnt, []*labelfilter.LabelFilter{filter}).Return(applicationModel, nil).Once()
  3665  				return repo
  3666  			},
  3667  			ExpectedApplication: applicationModel,
  3668  		},
  3669  		{
  3670  			Name: "Returns error when application retrieval failed",
  3671  			Ctx:  ctx,
  3672  			RepositoryFn: func() *automock.ApplicationRepository {
  3673  				repo := &automock.ApplicationRepository{}
  3674  				repo.On("GetByFilter", ctx, tnt, []*labelfilter.LabelFilter{filter}).Return(nil, testErr).Once()
  3675  				return repo
  3676  			},
  3677  			ExpectedErrMessage: testErr.Error(),
  3678  		},
  3679  		{
  3680  			Name:               "Returns error when extracting tenant from context",
  3681  			Ctx:                context.TODO(),
  3682  			RepositoryFn:       UnusedApplicationRepository,
  3683  			ExpectedErrMessage: "while loading tenant from context:",
  3684  		},
  3685  	}
  3686  
  3687  	for _, testCase := range testCases {
  3688  		t.Run(testCase.Name, func(t *testing.T) {
  3689  			repo := testCase.RepositoryFn()
  3690  
  3691  			svc := application.NewService(nil, nil, repo, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  3692  
  3693  			// WHEN
  3694  			app, err := svc.GetSccSystem(testCase.Ctx, "id", locationID, virtualHost)
  3695  
  3696  			// then
  3697  			if testCase.ExpectedErrMessage == "" {
  3698  				require.NoError(t, err)
  3699  				assert.Equal(t, testCase.ExpectedApplication, app)
  3700  			} else {
  3701  				require.Error(t, err)
  3702  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  3703  			}
  3704  
  3705  			repo.AssertExpectations(t)
  3706  		})
  3707  	}
  3708  }
  3709  
  3710  func TestService_List(t *testing.T) {
  3711  	// GIVEN
  3712  	testErr := errors.New("Test error")
  3713  
  3714  	modelApplications := []*model.Application{
  3715  		fixModelApplication("foo", "tenant-foo", "foo", "Lorem Ipsum"),
  3716  		fixModelApplication("bar", "tenant-bar", "bar", "Lorem Ipsum"),
  3717  	}
  3718  	applicationPage := &model.ApplicationPage{
  3719  		Data:       modelApplications,
  3720  		TotalCount: len(modelApplications),
  3721  		PageInfo: &pagination.Page{
  3722  			HasNextPage: false,
  3723  			EndCursor:   "end",
  3724  			StartCursor: "start",
  3725  		},
  3726  	}
  3727  
  3728  	first := 2
  3729  	after := "test"
  3730  	filter := []*labelfilter.LabelFilter{{Key: ""}}
  3731  
  3732  	tnt := "tenant"
  3733  	externalTnt := "external-tnt"
  3734  
  3735  	ctx := context.TODO()
  3736  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  3737  
  3738  	testCases := []struct {
  3739  		Name               string
  3740  		RepositoryFn       func() *automock.ApplicationRepository
  3741  		InputLabelFilters  []*labelfilter.LabelFilter
  3742  		InputPageSize      int
  3743  		ExpectedResult     *model.ApplicationPage
  3744  		ExpectedErrMessage string
  3745  	}{
  3746  		{
  3747  			Name: "Success",
  3748  			RepositoryFn: func() *automock.ApplicationRepository {
  3749  				repo := &automock.ApplicationRepository{}
  3750  				repo.On("List", ctx, tnt, filter, first, after).Return(applicationPage, nil).Once()
  3751  				return repo
  3752  			},
  3753  			InputPageSize:      first,
  3754  			InputLabelFilters:  filter,
  3755  			ExpectedResult:     applicationPage,
  3756  			ExpectedErrMessage: "",
  3757  		},
  3758  		{
  3759  			Name: "Returns error when application listing failed",
  3760  			RepositoryFn: func() *automock.ApplicationRepository {
  3761  				repo := &automock.ApplicationRepository{}
  3762  				repo.On("List", ctx, tnt, filter, first, after).Return(nil, testErr).Once()
  3763  				return repo
  3764  			},
  3765  			InputPageSize:      first,
  3766  			InputLabelFilters:  filter,
  3767  			ExpectedResult:     nil,
  3768  			ExpectedErrMessage: testErr.Error(),
  3769  		},
  3770  		{
  3771  			Name:         "Returns error when page size is less than 1",
  3772  			RepositoryFn: UnusedApplicationRepository,
  3773  
  3774  			InputPageSize:      0,
  3775  			InputLabelFilters:  filter,
  3776  			ExpectedResult:     nil,
  3777  			ExpectedErrMessage: "page size must be between 1 and 200",
  3778  		},
  3779  		{
  3780  			Name:         "Returns error when page size is bigger than 200",
  3781  			RepositoryFn: UnusedApplicationRepository,
  3782  
  3783  			InputPageSize:      201,
  3784  			InputLabelFilters:  filter,
  3785  			ExpectedResult:     nil,
  3786  			ExpectedErrMessage: "page size must be between 1 and 200",
  3787  		},
  3788  	}
  3789  
  3790  	for _, testCase := range testCases {
  3791  		t.Run(testCase.Name, func(t *testing.T) {
  3792  			repo := testCase.RepositoryFn()
  3793  
  3794  			svc := application.NewService(nil, nil, repo, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  3795  
  3796  			// WHEN
  3797  			app, err := svc.List(ctx, testCase.InputLabelFilters, testCase.InputPageSize, after)
  3798  
  3799  			// then
  3800  			if testCase.ExpectedErrMessage == "" {
  3801  				require.NoError(t, err)
  3802  				assert.Equal(t, testCase.ExpectedResult, app)
  3803  			} else {
  3804  				require.Error(t, err)
  3805  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  3806  			}
  3807  
  3808  			repo.AssertExpectations(t)
  3809  		})
  3810  	}
  3811  }
  3812  
  3813  func TestService_ListAll(t *testing.T) {
  3814  	// GIVEN
  3815  	testErr := errors.New("Test error")
  3816  
  3817  	modelApplications := []*model.Application{
  3818  		fixModelApplication("foo", "tenant-foo", "foo", "Lorem Ipsum"),
  3819  		fixModelApplication("bar", "tenant-bar", "bar", "Lorem Ipsum"),
  3820  	}
  3821  	tnt := "tenant"
  3822  	externalTnt := "external-tnt"
  3823  
  3824  	ctxEmpty := context.TODO()
  3825  	ctx := context.TODO()
  3826  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  3827  
  3828  	testCases := []struct {
  3829  		Name               string
  3830  		Context            context.Context
  3831  		RepositoryFn       func() *automock.ApplicationRepository
  3832  		ExpectedResult     []*model.Application
  3833  		ExpectedErrMessage string
  3834  	}{
  3835  		{
  3836  			Name:    "Success",
  3837  			Context: ctx,
  3838  			RepositoryFn: func() *automock.ApplicationRepository {
  3839  				repo := &automock.ApplicationRepository{}
  3840  				repo.On("ListAll", ctx, tnt).Return(modelApplications, nil).Once()
  3841  				return repo
  3842  			},
  3843  
  3844  			ExpectedResult:     modelApplications,
  3845  			ExpectedErrMessage: "",
  3846  		},
  3847  		{
  3848  			Name:    "Returns error when application listing failed",
  3849  			Context: ctx,
  3850  			RepositoryFn: func() *automock.ApplicationRepository {
  3851  				repo := &automock.ApplicationRepository{}
  3852  				repo.On("ListAll", ctx, tnt).Return(nil, testErr).Once()
  3853  				return repo
  3854  			},
  3855  			ExpectedResult:     nil,
  3856  			ExpectedErrMessage: testErr.Error(),
  3857  		},
  3858  		{
  3859  			Name:    "Returns error when tenant is not in the context",
  3860  			Context: ctxEmpty,
  3861  			RepositoryFn: func() *automock.ApplicationRepository {
  3862  				repo := &automock.ApplicationRepository{}
  3863  				repo.AssertNotCalled(t, "ListAll")
  3864  				return repo
  3865  			},
  3866  			ExpectedResult:     nil,
  3867  			ExpectedErrMessage: "cannot read tenant from context",
  3868  		},
  3869  	}
  3870  
  3871  	for _, testCase := range testCases {
  3872  		t.Run(testCase.Name, func(t *testing.T) {
  3873  			// GIVEN
  3874  			repo := testCase.RepositoryFn()
  3875  			defer mock.AssertExpectationsForObjects(t, repo)
  3876  
  3877  			svc := application.NewService(nil, nil, repo, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  3878  
  3879  			// WHEN
  3880  			app, err := svc.ListAll(testCase.Context)
  3881  
  3882  			// THEN
  3883  			if testCase.ExpectedErrMessage == "" {
  3884  				require.NoError(t, err)
  3885  				assert.Equal(t, testCase.ExpectedResult, app)
  3886  			} else {
  3887  				require.Error(t, err)
  3888  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  3889  			}
  3890  		})
  3891  	}
  3892  }
  3893  
  3894  func TestService_ListByRuntimeID(t *testing.T) {
  3895  	runtimeUUID := uuid.New()
  3896  	testError := errors.New("test error")
  3897  	tenantUUID := uuid.New()
  3898  	externalTenantUUID := uuid.New()
  3899  	ctx := context.TODO()
  3900  	ctx = tenant.SaveToContext(ctx, tenantUUID.String(), externalTenantUUID.String())
  3901  
  3902  	first := 10
  3903  	cursor := "test"
  3904  	scenarios := []interface{}{"Easter", "Christmas", "Winter-Sale"}
  3905  	scenarioLabel := model.Label{
  3906  		ID:    uuid.New().String(),
  3907  		Key:   model.ScenariosKey,
  3908  		Value: scenarios,
  3909  	}
  3910  	hidingSelectors := map[string][]string{"foo": {"bar", "baz"}}
  3911  
  3912  	applications := []*model.Application{
  3913  		fixModelApplication("test1", "tenant-foo", "test1", "test1"),
  3914  		fixModelApplication("test2", "tenant-foo", "test2", "test2"),
  3915  	}
  3916  	applicationPage := fixApplicationPage(applications)
  3917  	emptyPage := model.ApplicationPage{
  3918  		TotalCount: 0,
  3919  		Data:       []*model.Application{},
  3920  		PageInfo:   &pagination.Page{StartCursor: "", EndCursor: "", HasNextPage: false}}
  3921  
  3922  	testCases := []struct {
  3923  		Name                string
  3924  		Input               uuid.UUID
  3925  		RuntimeRepositoryFn func() *automock.RuntimeRepository
  3926  		LabelRepositoryFn   func() *automock.LabelRepository
  3927  		AppRepositoryFn     func() *automock.ApplicationRepository
  3928  		ConfigProviderFn    func() *automock.ApplicationHideCfgProvider
  3929  		ExpectedResult      *model.ApplicationPage
  3930  		ExpectedError       error
  3931  	}{
  3932  		{
  3933  			Name:  "Success",
  3934  			Input: runtimeUUID,
  3935  			RuntimeRepositoryFn: func() *automock.RuntimeRepository {
  3936  				runtimeRepository := &automock.RuntimeRepository{}
  3937  				runtimeRepository.On("Exists", ctx, tenantUUID.String(), runtimeUUID.String()).
  3938  					Return(true, nil).Once()
  3939  				return runtimeRepository
  3940  			},
  3941  			LabelRepositoryFn: func() *automock.LabelRepository {
  3942  				labelRepository := &automock.LabelRepository{}
  3943  				labelRepository.On("GetByKey", ctx, tenantUUID.String(), model.RuntimeLabelableObject, runtimeUUID.String(), model.ScenariosKey).
  3944  					Return(&scenarioLabel, nil).Once()
  3945  				return labelRepository
  3946  			},
  3947  			AppRepositoryFn: func() *automock.ApplicationRepository {
  3948  				appRepository := &automock.ApplicationRepository{}
  3949  				appRepository.On("ListByScenarios", ctx, tenantUUID, convertToStringArray(t, scenarios), first, cursor, hidingSelectors).
  3950  					Return(applicationPage, nil).Once()
  3951  				return appRepository
  3952  			},
  3953  			ConfigProviderFn: func() *automock.ApplicationHideCfgProvider {
  3954  				cfgProvider := &automock.ApplicationHideCfgProvider{}
  3955  				cfgProvider.On("GetApplicationHideSelectors").Return(hidingSelectors, nil).Once()
  3956  				return cfgProvider
  3957  			},
  3958  			ExpectedError:  nil,
  3959  			ExpectedResult: applicationPage,
  3960  		},
  3961  		{
  3962  			Name:  "Success when scenarios label not set",
  3963  			Input: runtimeUUID,
  3964  			RuntimeRepositoryFn: func() *automock.RuntimeRepository {
  3965  				runtimeRepository := &automock.RuntimeRepository{}
  3966  				runtimeRepository.On("Exists", ctx, tenantUUID.String(), runtimeUUID.String()).
  3967  					Return(true, nil).Once()
  3968  				return runtimeRepository
  3969  			},
  3970  			LabelRepositoryFn: func() *automock.LabelRepository {
  3971  				labelRepository := &automock.LabelRepository{}
  3972  				labelRepository.On("GetByKey", ctx, tenantUUID.String(), model.RuntimeLabelableObject, runtimeUUID.String(), model.ScenariosKey).
  3973  					Return(nil, apperrors.NewNotFoundError(resource.Application, "")).Once()
  3974  				return labelRepository
  3975  			},
  3976  			AppRepositoryFn: UnusedApplicationRepository,
  3977  			ConfigProviderFn: func() *automock.ApplicationHideCfgProvider {
  3978  				cfgProvider := &automock.ApplicationHideCfgProvider{}
  3979  				return cfgProvider
  3980  			},
  3981  			ExpectedError: nil,
  3982  			ExpectedResult: &model.ApplicationPage{
  3983  				Data:       []*model.Application{},
  3984  				PageInfo:   &pagination.Page{},
  3985  				TotalCount: 0,
  3986  			},
  3987  		},
  3988  		{
  3989  			Name:  "Return error when checking of runtime existence failed",
  3990  			Input: runtimeUUID,
  3991  			RuntimeRepositoryFn: func() *automock.RuntimeRepository {
  3992  				runtimeRepository := &automock.RuntimeRepository{}
  3993  				runtimeRepository.On("Exists", ctx, tenantUUID.String(), runtimeUUID.String()).
  3994  					Return(false, testError).Once()
  3995  				return runtimeRepository
  3996  			},
  3997  			LabelRepositoryFn: func() *automock.LabelRepository {
  3998  				labelRepository := &automock.LabelRepository{}
  3999  				return labelRepository
  4000  			},
  4001  			AppRepositoryFn: UnusedApplicationRepository,
  4002  			ConfigProviderFn: func() *automock.ApplicationHideCfgProvider {
  4003  				cfgProvider := &automock.ApplicationHideCfgProvider{}
  4004  				return cfgProvider
  4005  			},
  4006  			ExpectedError:  testError,
  4007  			ExpectedResult: nil,
  4008  		},
  4009  		{
  4010  			Name:  "Return error when runtime not exits",
  4011  			Input: runtimeUUID,
  4012  			RuntimeRepositoryFn: func() *automock.RuntimeRepository {
  4013  				runtimeRepository := &automock.RuntimeRepository{}
  4014  				runtimeRepository.On("Exists", ctx, tenantUUID.String(), runtimeUUID.String()).
  4015  					Return(false, nil).Once()
  4016  				return runtimeRepository
  4017  			},
  4018  			LabelRepositoryFn: func() *automock.LabelRepository {
  4019  				labelRepository := &automock.LabelRepository{}
  4020  				return labelRepository
  4021  			},
  4022  			AppRepositoryFn: UnusedApplicationRepository,
  4023  			ConfigProviderFn: func() *automock.ApplicationHideCfgProvider {
  4024  				cfgProvider := &automock.ApplicationHideCfgProvider{}
  4025  				return cfgProvider
  4026  			},
  4027  			ExpectedError:  errors.New("runtime does not exist"),
  4028  			ExpectedResult: nil,
  4029  		},
  4030  		{
  4031  			Name:  "Return error when getting runtime scenarios by RuntimeID failed",
  4032  			Input: runtimeUUID,
  4033  			RuntimeRepositoryFn: func() *automock.RuntimeRepository {
  4034  				runtimeRepository := &automock.RuntimeRepository{}
  4035  				runtimeRepository.On("Exists", ctx, tenantUUID.String(), runtimeUUID.String()).
  4036  					Return(true, nil).Once()
  4037  				return runtimeRepository
  4038  			},
  4039  			LabelRepositoryFn: func() *automock.LabelRepository {
  4040  				labelRepository := &automock.LabelRepository{}
  4041  				labelRepository.On("GetByKey", ctx, tenantUUID.String(), model.RuntimeLabelableObject, runtimeUUID.String(), model.ScenariosKey).
  4042  					Return(nil, testError).Once()
  4043  				return labelRepository
  4044  			},
  4045  			AppRepositoryFn: UnusedApplicationRepository,
  4046  			ConfigProviderFn: func() *automock.ApplicationHideCfgProvider {
  4047  				cfgProvider := &automock.ApplicationHideCfgProvider{}
  4048  				return cfgProvider
  4049  			},
  4050  			ExpectedError:  testError,
  4051  			ExpectedResult: nil,
  4052  		},
  4053  		{
  4054  			Name:  "Return error when listing application by scenarios failed",
  4055  			Input: runtimeUUID,
  4056  			RuntimeRepositoryFn: func() *automock.RuntimeRepository {
  4057  				runtimeRepository := &automock.RuntimeRepository{}
  4058  				runtimeRepository.On("Exists", ctx, tenantUUID.String(), runtimeUUID.String()).
  4059  					Return(true, nil).Once()
  4060  				return runtimeRepository
  4061  			},
  4062  			LabelRepositoryFn: func() *automock.LabelRepository {
  4063  				labelRepository := &automock.LabelRepository{}
  4064  				labelRepository.On("GetByKey", ctx, tenantUUID.String(), model.RuntimeLabelableObject, runtimeUUID.String(), model.ScenariosKey).
  4065  					Return(&scenarioLabel, nil).Once()
  4066  				return labelRepository
  4067  			},
  4068  			AppRepositoryFn: func() *automock.ApplicationRepository {
  4069  				appRepository := &automock.ApplicationRepository{}
  4070  				appRepository.On("ListByScenarios", ctx, tenantUUID, convertToStringArray(t, scenarios), first, cursor, hidingSelectors).
  4071  					Return(nil, testError).Once()
  4072  				return appRepository
  4073  			},
  4074  			ConfigProviderFn: func() *automock.ApplicationHideCfgProvider {
  4075  				cfgProvider := &automock.ApplicationHideCfgProvider{}
  4076  				cfgProvider.On("GetApplicationHideSelectors").Return(hidingSelectors, nil).Once()
  4077  				return cfgProvider
  4078  			},
  4079  			ExpectedError:  testError,
  4080  			ExpectedResult: nil,
  4081  		},
  4082  		{
  4083  			Name:  "Return empty page when runtime is not assigned to any scenario",
  4084  			Input: runtimeUUID,
  4085  			RuntimeRepositoryFn: func() *automock.RuntimeRepository {
  4086  				runtimeRepository := &automock.RuntimeRepository{}
  4087  				runtimeRepository.On("Exists", ctx, tenantUUID.String(), runtimeUUID.String()).
  4088  					Return(true, nil).Once()
  4089  				return runtimeRepository
  4090  			},
  4091  			LabelRepositoryFn: func() *automock.LabelRepository {
  4092  				labelRepository := &automock.LabelRepository{}
  4093  				labelRepository.On("GetByKey", ctx, tenantUUID.String(), model.RuntimeLabelableObject, runtimeUUID.String(), model.ScenariosKey).
  4094  					Return(&model.Label{ID: uuid.New().String(), Key: model.ScenariosKey, Value: []interface{}{}}, nil).Once()
  4095  				return labelRepository
  4096  			},
  4097  			AppRepositoryFn: UnusedApplicationRepository,
  4098  			ConfigProviderFn: func() *automock.ApplicationHideCfgProvider {
  4099  				cfgProvider := &automock.ApplicationHideCfgProvider{}
  4100  				return cfgProvider
  4101  			},
  4102  			ExpectedError:  nil,
  4103  			ExpectedResult: &emptyPage,
  4104  		},
  4105  		{
  4106  			Name:  "Return error when config provider returns error",
  4107  			Input: runtimeUUID,
  4108  			RuntimeRepositoryFn: func() *automock.RuntimeRepository {
  4109  				runtimeRepository := &automock.RuntimeRepository{}
  4110  				runtimeRepository.On("Exists", ctx, tenantUUID.String(), runtimeUUID.String()).
  4111  					Return(true, nil).Once()
  4112  				return runtimeRepository
  4113  			},
  4114  			LabelRepositoryFn: func() *automock.LabelRepository {
  4115  				labelRepository := &automock.LabelRepository{}
  4116  				labelRepository.On("GetByKey", ctx, tenantUUID.String(), model.RuntimeLabelableObject, runtimeUUID.String(), model.ScenariosKey).
  4117  					Return(&scenarioLabel, nil).Once()
  4118  				return labelRepository
  4119  			},
  4120  			AppRepositoryFn: UnusedApplicationRepository,
  4121  			ConfigProviderFn: func() *automock.ApplicationHideCfgProvider {
  4122  				cfgProvider := &automock.ApplicationHideCfgProvider{}
  4123  				cfgProvider.On("GetApplicationHideSelectors").Return(nil, testError).Once()
  4124  				return cfgProvider
  4125  			},
  4126  			ExpectedError:  testError,
  4127  			ExpectedResult: nil,
  4128  		},
  4129  	}
  4130  
  4131  	for _, testCase := range testCases {
  4132  		t.Run(testCase.Name, func(t *testing.T) {
  4133  			// GIVEN
  4134  			runtimeRepository := testCase.RuntimeRepositoryFn()
  4135  			labelRepository := testCase.LabelRepositoryFn()
  4136  			appRepository := testCase.AppRepositoryFn()
  4137  			cfgProvider := testCase.ConfigProviderFn()
  4138  			svc := application.NewService(nil, cfgProvider, appRepository, nil, runtimeRepository, labelRepository, nil, nil, nil, nil, nil, "", nil)
  4139  
  4140  			// WHEN
  4141  			results, err := svc.ListByRuntimeID(ctx, testCase.Input, first, cursor)
  4142  
  4143  			// THEN
  4144  			if testCase.ExpectedError != nil {
  4145  				require.Error(t, err)
  4146  				assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
  4147  			} else {
  4148  				logrus.Info(err)
  4149  				require.NoError(t, err)
  4150  			}
  4151  			assert.Equal(t, testCase.ExpectedResult, results)
  4152  			mock.AssertExpectationsForObjects(t, runtimeRepository, labelRepository, appRepository, cfgProvider)
  4153  		})
  4154  	}
  4155  }
  4156  
  4157  func TestService_ListBySCC(t *testing.T) {
  4158  	// GIVEN
  4159  	testErr := errors.New("test error")
  4160  
  4161  	tnt := "tenant"
  4162  
  4163  	app1ID := "foo"
  4164  	app2ID := "bar"
  4165  
  4166  	app1 := fixModelApplication(app1ID, tnt, "foo", "Lorem Ipsum")
  4167  	app2 := fixModelApplication(app2ID, tnt, "bar", "Lorem Ipsum")
  4168  	applications := []*model.Application{app1, app2}
  4169  
  4170  	labelValue := stringPtr("{\"locationId\":\"locationId\", \"subaccount\":\"tenant\"}")
  4171  
  4172  	label1 := &model.Label{
  4173  		ObjectID: app1ID,
  4174  		Value:    labelValue,
  4175  	}
  4176  
  4177  	label2 := &model.Label{
  4178  		ObjectID: app2ID,
  4179  		Value:    labelValue,
  4180  	}
  4181  
  4182  	applicationsWitLabel := []*model.ApplicationWithLabel{
  4183  		{
  4184  			App:      app1,
  4185  			SccLabel: label1,
  4186  		},
  4187  		{
  4188  			App:      app2,
  4189  			SccLabel: label2,
  4190  		},
  4191  	}
  4192  
  4193  	filter := &labelfilter.LabelFilter{Key: "scc", Query: stringPtr("{\"locationId\":\"locationId\", \"subaccount\":\"tenant\"}")}
  4194  
  4195  	externalTnt := "external-tnt"
  4196  
  4197  	ctx := context.TODO()
  4198  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  4199  
  4200  	testCases := []struct {
  4201  		Name               string
  4202  		Ctx                context.Context
  4203  		RepositoryFn       func() *automock.ApplicationRepository
  4204  		LabelRepositoryFn  func() *automock.LabelRepository
  4205  		InputLabelFilter   *labelfilter.LabelFilter
  4206  		ExpectedResult     []*model.ApplicationWithLabel
  4207  		ExpectedErrMessage string
  4208  	}{
  4209  		{
  4210  			Name: "Success",
  4211  			Ctx:  ctx,
  4212  			RepositoryFn: func() *automock.ApplicationRepository {
  4213  				repo := &automock.ApplicationRepository{}
  4214  				repo.On("ListAllByFilter", ctx, tnt, []*labelfilter.LabelFilter{filter}).Return(applications, nil).Once()
  4215  				return repo
  4216  			},
  4217  			LabelRepositoryFn: func() *automock.LabelRepository {
  4218  				repo := &automock.LabelRepository{}
  4219  				repo.On("ListGlobalByKeyAndObjects", ctx, model.ApplicationLabelableObject, []string{app1ID, app2ID}, "scc").Return([]*model.Label{label1, label2}, nil)
  4220  				return repo
  4221  			},
  4222  			InputLabelFilter:   filter,
  4223  			ExpectedResult:     applicationsWitLabel,
  4224  			ExpectedErrMessage: "",
  4225  		},
  4226  		{
  4227  			Name: "Success when no apps matching the filter are found",
  4228  			Ctx:  ctx,
  4229  			RepositoryFn: func() *automock.ApplicationRepository {
  4230  				repo := &automock.ApplicationRepository{}
  4231  				repo.On("ListAllByFilter", ctx, tnt, []*labelfilter.LabelFilter{filter}).Return([]*model.Application{}, nil).Once()
  4232  				return repo
  4233  			},
  4234  			LabelRepositoryFn:  UnusedLabelRepository,
  4235  			InputLabelFilter:   filter,
  4236  			ExpectedResult:     []*model.ApplicationWithLabel{},
  4237  			ExpectedErrMessage: "",
  4238  		},
  4239  		{
  4240  			Name: "Returns error when failed to list labels for applications",
  4241  			Ctx:  ctx,
  4242  			RepositoryFn: func() *automock.ApplicationRepository {
  4243  				repo := &automock.ApplicationRepository{}
  4244  				repo.On("ListAllByFilter", ctx, tnt, []*labelfilter.LabelFilter{filter}).Return(applications, nil).Once()
  4245  				return repo
  4246  			},
  4247  			LabelRepositoryFn: func() *automock.LabelRepository {
  4248  				repo := &automock.LabelRepository{}
  4249  				repo.On("ListGlobalByKeyAndObjects", ctx, model.ApplicationLabelableObject, []string{app1ID, app2ID}, "scc").Return(nil, testErr)
  4250  				return repo
  4251  			},
  4252  			InputLabelFilter:   filter,
  4253  			ExpectedResult:     nil,
  4254  			ExpectedErrMessage: "while getting labels with key scc for applications with IDs:",
  4255  		},
  4256  		{
  4257  			Name: "Returns error when application listing failed",
  4258  			Ctx:  ctx,
  4259  			RepositoryFn: func() *automock.ApplicationRepository {
  4260  				repo := &automock.ApplicationRepository{}
  4261  				repo.On("ListAllByFilter", ctx, tnt, []*labelfilter.LabelFilter{filter}).Return(nil, testErr).Once()
  4262  				return repo
  4263  			},
  4264  			LabelRepositoryFn:  UnusedLabelRepository,
  4265  			InputLabelFilter:   filter,
  4266  			ExpectedResult:     nil,
  4267  			ExpectedErrMessage: testErr.Error(),
  4268  		},
  4269  		{
  4270  			Name:         "Returns error when extracting tenant from context",
  4271  			Ctx:          context.TODO(),
  4272  			RepositoryFn: UnusedApplicationRepository,
  4273  
  4274  			LabelRepositoryFn:  UnusedLabelRepository,
  4275  			ExpectedErrMessage: "while loading tenant from context:",
  4276  		},
  4277  	}
  4278  
  4279  	for _, testCase := range testCases {
  4280  		t.Run(testCase.Name, func(t *testing.T) {
  4281  			appRepo := testCase.RepositoryFn()
  4282  			labelRepo := testCase.LabelRepositoryFn()
  4283  			svc := application.NewService(nil, nil, appRepo, nil, nil, labelRepo, nil, nil, nil, nil, nil, "", nil)
  4284  
  4285  			// WHEN
  4286  			app, err := svc.ListBySCC(testCase.Ctx, filter)
  4287  
  4288  			// then
  4289  			if testCase.ExpectedErrMessage == "" {
  4290  				require.NoError(t, err)
  4291  				assert.Equal(t, testCase.ExpectedResult, app)
  4292  			} else {
  4293  				require.Error(t, err)
  4294  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  4295  			}
  4296  
  4297  			appRepo.AssertExpectations(t)
  4298  		})
  4299  	}
  4300  }
  4301  
  4302  func TestService_ListSCCs(t *testing.T) {
  4303  	// GIVEN
  4304  	testErr := errors.New("test error")
  4305  
  4306  	tnt := "tenant"
  4307  
  4308  	key := "scc"
  4309  
  4310  	locationID1 := "locationID1"
  4311  	locationID2 := "locationID2"
  4312  	subaccount1 := "subaccount1"
  4313  	subaccount2 := "subaccount2"
  4314  
  4315  	labelValue1 := map[string]interface{}{"LocationID": locationID1, "Subaccount": subaccount1}
  4316  	labelValue2 := map[string]interface{}{"LocationID": locationID2, "Subaccount": subaccount2}
  4317  
  4318  	labels := []*model.Label{
  4319  		{Value: labelValue1},
  4320  		{Value: labelValue2},
  4321  	}
  4322  
  4323  	sccs := []*model.SccMetadata{
  4324  		{
  4325  			Subaccount: subaccount1,
  4326  			LocationID: locationID1,
  4327  		},
  4328  		{
  4329  			Subaccount: subaccount2,
  4330  			LocationID: locationID2,
  4331  		},
  4332  	}
  4333  
  4334  	filter := &labelfilter.LabelFilter{Key: "scc", Query: stringPtr("{\"locationId\":\"locationId\", \"subaccount\":\"tenant\"}")}
  4335  
  4336  	externalTnt := "external-tnt"
  4337  
  4338  	ctx := context.TODO()
  4339  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  4340  
  4341  	testCases := []struct {
  4342  		Name               string
  4343  		Ctx                context.Context
  4344  		RepositoryFn       func() *automock.LabelRepository
  4345  		InputLabelFilter   *labelfilter.LabelFilter
  4346  		ExpectedResult     []*model.SccMetadata
  4347  		ExpectedErrMessage string
  4348  	}{
  4349  		{
  4350  			Name: "Success",
  4351  			Ctx:  ctx,
  4352  			RepositoryFn: func() *automock.LabelRepository {
  4353  				repo := &automock.LabelRepository{}
  4354  				repo.On("ListGlobalByKey", ctx, key).Return(labels, nil).Once()
  4355  				return repo
  4356  			},
  4357  			InputLabelFilter:   filter,
  4358  			ExpectedResult:     sccs,
  4359  			ExpectedErrMessage: "",
  4360  		},
  4361  		{
  4362  			Name: "Returns error when labels listing failed",
  4363  			Ctx:  ctx,
  4364  			RepositoryFn: func() *automock.LabelRepository {
  4365  				repo := &automock.LabelRepository{}
  4366  				repo.On("ListGlobalByKey", ctx, key).Return(nil, testErr).Once()
  4367  				return repo
  4368  			},
  4369  			InputLabelFilter:   filter,
  4370  			ExpectedResult:     nil,
  4371  			ExpectedErrMessage: testErr.Error(),
  4372  		},
  4373  	}
  4374  
  4375  	for _, testCase := range testCases {
  4376  		t.Run(testCase.Name, func(t *testing.T) {
  4377  			repo := testCase.RepositoryFn()
  4378  
  4379  			svc := application.NewService(nil, nil, nil, nil, nil, repo, nil, nil, nil, nil, nil, "", nil)
  4380  
  4381  			// WHEN
  4382  			app, err := svc.ListSCCs(testCase.Ctx)
  4383  
  4384  			// then
  4385  			if testCase.ExpectedErrMessage == "" {
  4386  				require.NoError(t, err)
  4387  				assert.Equal(t, testCase.ExpectedResult, app)
  4388  			} else {
  4389  				require.Error(t, err)
  4390  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  4391  			}
  4392  
  4393  			repo.AssertExpectations(t)
  4394  		})
  4395  	}
  4396  }
  4397  
  4398  func TestService_Exist(t *testing.T) {
  4399  	tnt := "tenant"
  4400  	externalTnt := "external-tnt"
  4401  
  4402  	ctx := context.TODO()
  4403  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  4404  	testError := errors.New("Test error")
  4405  
  4406  	applicationID := "id"
  4407  
  4408  	testCases := []struct {
  4409  		Name               string
  4410  		RepositoryFn       func() *automock.ApplicationRepository
  4411  		InputApplicationID string
  4412  		ExptectedValue     bool
  4413  		ExpectedError      error
  4414  	}{
  4415  		{
  4416  			Name: "Application exits",
  4417  			RepositoryFn: func() *automock.ApplicationRepository {
  4418  				repo := &automock.ApplicationRepository{}
  4419  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil)
  4420  				return repo
  4421  			},
  4422  			InputApplicationID: applicationID,
  4423  			ExptectedValue:     true,
  4424  			ExpectedError:      nil,
  4425  		},
  4426  		{
  4427  			Name: "Application not exits",
  4428  			RepositoryFn: func() *automock.ApplicationRepository {
  4429  				repo := &automock.ApplicationRepository{}
  4430  				repo.On("Exists", ctx, tnt, applicationID).Return(false, nil)
  4431  				return repo
  4432  			},
  4433  			InputApplicationID: applicationID,
  4434  			ExptectedValue:     false,
  4435  			ExpectedError:      nil,
  4436  		},
  4437  		{
  4438  			Name: "Returns error",
  4439  			RepositoryFn: func() *automock.ApplicationRepository {
  4440  				repo := &automock.ApplicationRepository{}
  4441  				repo.On("Exists", ctx, tnt, applicationID).Return(false, testError)
  4442  				return repo
  4443  			},
  4444  			InputApplicationID: applicationID,
  4445  			ExptectedValue:     false,
  4446  			ExpectedError:      testError,
  4447  		},
  4448  	}
  4449  
  4450  	for _, testCase := range testCases {
  4451  		t.Run(testCase.Name, func(t *testing.T) {
  4452  			// GIVEN
  4453  			appRepo := testCase.RepositoryFn()
  4454  			svc := application.NewService(nil, nil, appRepo, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  4455  
  4456  			// WHEN
  4457  			value, err := svc.Exist(ctx, testCase.InputApplicationID)
  4458  
  4459  			// THEN
  4460  			if testCase.ExpectedError != nil {
  4461  				require.Error(t, err)
  4462  				assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
  4463  			} else {
  4464  				require.Nil(t, err)
  4465  			}
  4466  
  4467  			assert.Equal(t, testCase.ExptectedValue, value)
  4468  			appRepo.AssertExpectations(t)
  4469  		})
  4470  	}
  4471  }
  4472  
  4473  func TestService_SetLabel(t *testing.T) {
  4474  	// GIVEN
  4475  	tnt := "tenant"
  4476  	externalTnt := "external-tnt"
  4477  
  4478  	ctx := context.TODO()
  4479  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  4480  
  4481  	testErr := errors.New("Test error")
  4482  
  4483  	applicationID := "foo"
  4484  
  4485  	label := &model.LabelInput{
  4486  		Key:        "key",
  4487  		Value:      []string{"value1"},
  4488  		ObjectID:   applicationID,
  4489  		ObjectType: model.ApplicationLabelableObject,
  4490  	}
  4491  
  4492  	newScenario := "new-scenario"
  4493  	extraScenario := "unnecessary-scenario"
  4494  	scenarioLabel := &model.LabelInput{
  4495  		Key:        model.ScenariosKey,
  4496  		Value:      []interface{}{testScenario, newScenario},
  4497  		ObjectID:   applicationID,
  4498  		ObjectType: model.ApplicationLabelableObject,
  4499  	}
  4500  
  4501  	testCases := []struct {
  4502  		Name               string
  4503  		RepositoryFn       func() *automock.ApplicationRepository
  4504  		LabelRepoFn        func() *automock.LabelRepository
  4505  		LabelServiceFn     func() *automock.LabelService
  4506  		FormationServiceFn func() *automock.FormationService
  4507  		InputApplicationID string
  4508  		InputLabel         *model.LabelInput
  4509  		ExpectedErrMessage string
  4510  	}{
  4511  		{
  4512  			Name: "Success",
  4513  			RepositoryFn: func() *automock.ApplicationRepository {
  4514  				repo := &automock.ApplicationRepository{}
  4515  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4516  
  4517  				return repo
  4518  			},
  4519  			LabelRepoFn: func() *automock.LabelRepository {
  4520  				svc := &automock.LabelRepository{}
  4521  				return svc
  4522  			},
  4523  			LabelServiceFn: func() *automock.LabelService {
  4524  				svc := &automock.LabelService{}
  4525  				svc.On("UpsertLabel", ctx, tnt, label).Return(nil).Once()
  4526  				return svc
  4527  			},
  4528  			FormationServiceFn: UnusedFormationService,
  4529  			InputApplicationID: applicationID,
  4530  			InputLabel:         label,
  4531  			ExpectedErrMessage: "",
  4532  		},
  4533  		{
  4534  			Name: "Returns error when label set failed",
  4535  			RepositoryFn: func() *automock.ApplicationRepository {
  4536  				repo := &automock.ApplicationRepository{}
  4537  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4538  
  4539  				return repo
  4540  			},
  4541  			LabelRepoFn: func() *automock.LabelRepository {
  4542  				svc := &automock.LabelRepository{}
  4543  				return svc
  4544  			},
  4545  			LabelServiceFn: func() *automock.LabelService {
  4546  				svc := &automock.LabelService{}
  4547  				svc.On("UpsertLabel", ctx, tnt, label).Return(testErr).Once()
  4548  				return svc
  4549  			},
  4550  			FormationServiceFn: UnusedFormationService,
  4551  			InputApplicationID: applicationID,
  4552  			InputLabel:         label,
  4553  			ExpectedErrMessage: testErr.Error(),
  4554  		},
  4555  		{
  4556  			Name: "Returns error when application retrieval failed",
  4557  			RepositoryFn: func() *automock.ApplicationRepository {
  4558  				repo := &automock.ApplicationRepository{}
  4559  				repo.On("Exists", ctx, tnt, applicationID).Return(false, testErr).Once()
  4560  
  4561  				return repo
  4562  			},
  4563  			LabelRepoFn: func() *automock.LabelRepository {
  4564  				svc := &automock.LabelRepository{}
  4565  				return svc
  4566  			},
  4567  			LabelServiceFn:     UnusedLabelService,
  4568  			FormationServiceFn: UnusedFormationService,
  4569  			InputApplicationID: applicationID,
  4570  			InputLabel:         label,
  4571  			ExpectedErrMessage: testErr.Error(),
  4572  		},
  4573  		{
  4574  			Name: "Success when all calls to formation service succeed",
  4575  			RepositoryFn: func() *automock.ApplicationRepository {
  4576  				repo := &automock.ApplicationRepository{}
  4577  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4578  
  4579  				return repo
  4580  			},
  4581  			LabelRepoFn: func() *automock.LabelRepository {
  4582  				repo := &automock.LabelRepository{}
  4583  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationID, model.ScenariosKey).Return(&model.Label{
  4584  					Tenant:     &tnt,
  4585  					Key:        model.ScenariosKey,
  4586  					Value:      []interface{}{testScenario, extraScenario},
  4587  					ObjectID:   applicationID,
  4588  					ObjectType: model.ApplicationLabelableObject,
  4589  					Version:    0,
  4590  				}, nil)
  4591  				return repo
  4592  			},
  4593  			LabelServiceFn: UnusedLabelService,
  4594  			FormationServiceFn: func() *automock.FormationService {
  4595  				svc := &automock.FormationService{}
  4596  				svc.On("AssignFormation", ctx, tnt, applicationID, graphql.FormationObjectTypeApplication, model.Formation{Name: newScenario}).Return(nil, nil).Once()
  4597  				svc.On("UnassignFormation", ctx, tnt, applicationID, graphql.FormationObjectTypeApplication, model.Formation{Name: extraScenario}).Return(nil, nil).Once()
  4598  				return svc
  4599  			},
  4600  			InputApplicationID: applicationID,
  4601  			InputLabel:         scenarioLabel,
  4602  			ExpectedErrMessage: "",
  4603  		},
  4604  		{
  4605  			Name: "Error when call to AssignFormation fails",
  4606  			RepositoryFn: func() *automock.ApplicationRepository {
  4607  				repo := &automock.ApplicationRepository{}
  4608  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4609  
  4610  				return repo
  4611  			},
  4612  			LabelRepoFn: func() *automock.LabelRepository {
  4613  				repo := &automock.LabelRepository{}
  4614  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationID, model.ScenariosKey).Return(&model.Label{
  4615  					Tenant:     &tnt,
  4616  					Key:        model.ScenariosKey,
  4617  					Value:      []interface{}{testScenario, extraScenario},
  4618  					ObjectID:   applicationID,
  4619  					ObjectType: model.ApplicationLabelableObject,
  4620  					Version:    0,
  4621  				}, nil)
  4622  				return repo
  4623  			},
  4624  			LabelServiceFn: UnusedLabelService,
  4625  			FormationServiceFn: func() *automock.FormationService {
  4626  				svc := &automock.FormationService{}
  4627  				svc.On("AssignFormation", ctx, tnt, applicationID, graphql.FormationObjectTypeApplication, model.Formation{Name: newScenario}).Return(nil, testErr).Once()
  4628  				return svc
  4629  			},
  4630  			InputApplicationID: applicationID,
  4631  			InputLabel:         scenarioLabel,
  4632  			ExpectedErrMessage: testErr.Error(),
  4633  		},
  4634  		{
  4635  			Name: "Error when call to UnassignFormation fails",
  4636  			RepositoryFn: func() *automock.ApplicationRepository {
  4637  				repo := &automock.ApplicationRepository{}
  4638  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4639  
  4640  				return repo
  4641  			},
  4642  			LabelRepoFn: func() *automock.LabelRepository {
  4643  				repo := &automock.LabelRepository{}
  4644  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationID, model.ScenariosKey).Return(&model.Label{
  4645  					Tenant:     &tnt,
  4646  					Key:        model.ScenariosKey,
  4647  					Value:      []interface{}{testScenario, extraScenario},
  4648  					ObjectID:   applicationID,
  4649  					ObjectType: model.ApplicationLabelableObject,
  4650  					Version:    0,
  4651  				}, nil)
  4652  				return repo
  4653  			},
  4654  			LabelServiceFn: UnusedLabelService,
  4655  			FormationServiceFn: func() *automock.FormationService {
  4656  				svc := &automock.FormationService{}
  4657  				svc.On("AssignFormation", ctx, tnt, applicationID, graphql.FormationObjectTypeApplication, model.Formation{Name: newScenario}).Return(nil, nil).Once()
  4658  				svc.On("UnassignFormation", ctx, tnt, applicationID, graphql.FormationObjectTypeApplication, model.Formation{Name: extraScenario}).Return(nil, testErr).Once()
  4659  				return svc
  4660  			},
  4661  			InputApplicationID: applicationID,
  4662  			InputLabel:         scenarioLabel,
  4663  			ExpectedErrMessage: testErr.Error(),
  4664  		},
  4665  		{
  4666  			Name: "Success when scenario label does not exist",
  4667  			RepositoryFn: func() *automock.ApplicationRepository {
  4668  				repo := &automock.ApplicationRepository{}
  4669  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4670  
  4671  				return repo
  4672  			},
  4673  			LabelRepoFn: func() *automock.LabelRepository {
  4674  				repo := &automock.LabelRepository{}
  4675  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationID, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.Label, applicationID))
  4676  				return repo
  4677  			},
  4678  			LabelServiceFn: UnusedLabelService,
  4679  			FormationServiceFn: func() *automock.FormationService {
  4680  				svc := &automock.FormationService{}
  4681  				svc.On("AssignFormation", ctx, tnt, applicationID, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  4682  				svc.On("AssignFormation", ctx, tnt, applicationID, graphql.FormationObjectTypeApplication, model.Formation{Name: newScenario}).Return(nil, nil).Once()
  4683  				return svc
  4684  			},
  4685  			InputApplicationID: applicationID,
  4686  			InputLabel:         scenarioLabel,
  4687  			ExpectedErrMessage: "",
  4688  		},
  4689  		{
  4690  			Name: "Error when GetByKey call fails",
  4691  			RepositoryFn: func() *automock.ApplicationRepository {
  4692  				repo := &automock.ApplicationRepository{}
  4693  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4694  
  4695  				return repo
  4696  			},
  4697  			LabelRepoFn: func() *automock.LabelRepository {
  4698  				repo := &automock.LabelRepository{}
  4699  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationID, model.ScenariosKey).Return(nil, testErr)
  4700  				return repo
  4701  			},
  4702  			LabelServiceFn:     UnusedLabelService,
  4703  			FormationServiceFn: UnusedFormationService,
  4704  			InputApplicationID: applicationID,
  4705  			InputLabel:         scenarioLabel,
  4706  			ExpectedErrMessage: testErr.Error(),
  4707  		},
  4708  	}
  4709  
  4710  	for _, testCase := range testCases {
  4711  		t.Run(testCase.Name, func(t *testing.T) {
  4712  			repo := testCase.RepositoryFn()
  4713  			labelRepo := testCase.LabelRepoFn()
  4714  			labelSvc := testCase.LabelServiceFn()
  4715  			formationSvc := testCase.FormationServiceFn()
  4716  
  4717  			svc := application.NewService(nil, nil, repo, nil, nil, labelRepo, nil, labelSvc, nil, nil, formationSvc, "", nil)
  4718  
  4719  			// WHEN
  4720  			err := svc.SetLabel(ctx, testCase.InputLabel)
  4721  
  4722  			// then
  4723  			if testCase.ExpectedErrMessage == "" {
  4724  				require.NoError(t, err)
  4725  			} else {
  4726  				require.Error(t, err)
  4727  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  4728  			}
  4729  
  4730  			mock.AssertExpectationsForObjects(t, repo, labelRepo, labelSvc, formationSvc)
  4731  		})
  4732  	}
  4733  }
  4734  
  4735  func TestService_GetLabel(t *testing.T) {
  4736  	// GIVEN
  4737  	tnt := "tenant"
  4738  	externalTnt := "external-tnt"
  4739  
  4740  	ctx := context.TODO()
  4741  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  4742  
  4743  	testErr := errors.New("Test error")
  4744  
  4745  	applicationID := "foo"
  4746  	labelKey := "key"
  4747  	labelValue := []string{"value1"}
  4748  
  4749  	label := &model.LabelInput{
  4750  		Key:        labelKey,
  4751  		Value:      labelValue,
  4752  		ObjectID:   applicationID,
  4753  		ObjectType: model.ApplicationLabelableObject,
  4754  	}
  4755  
  4756  	modelLabel := &model.Label{
  4757  		ID:         "5d23d9d9-3d04-4fa9-95e6-d22e1ae62c11",
  4758  		Tenant:     str.Ptr(tnt),
  4759  		Key:        labelKey,
  4760  		Value:      labelValue,
  4761  		ObjectID:   applicationID,
  4762  		ObjectType: model.ApplicationLabelableObject,
  4763  	}
  4764  
  4765  	testCases := []struct {
  4766  		Name               string
  4767  		RepositoryFn       func() *automock.ApplicationRepository
  4768  		LabelRepositoryFn  func() *automock.LabelRepository
  4769  		InputApplicationID string
  4770  		InputLabel         *model.LabelInput
  4771  		ExpectedLabel      *model.Label
  4772  		ExpectedErrMessage string
  4773  	}{
  4774  		{
  4775  			Name: "Success",
  4776  			RepositoryFn: func() *automock.ApplicationRepository {
  4777  				repo := &automock.ApplicationRepository{}
  4778  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4779  				return repo
  4780  			},
  4781  			LabelRepositoryFn: func() *automock.LabelRepository {
  4782  				repo := &automock.LabelRepository{}
  4783  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationID, labelKey).Return(modelLabel, nil).Once()
  4784  				return repo
  4785  			},
  4786  			InputApplicationID: applicationID,
  4787  			InputLabel:         label,
  4788  			ExpectedLabel:      modelLabel,
  4789  			ExpectedErrMessage: "",
  4790  		},
  4791  		{
  4792  			Name: "Returns error when label receiving failed",
  4793  			RepositoryFn: func() *automock.ApplicationRepository {
  4794  				repo := &automock.ApplicationRepository{}
  4795  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4796  
  4797  				return repo
  4798  			},
  4799  			LabelRepositoryFn: func() *automock.LabelRepository {
  4800  				repo := &automock.LabelRepository{}
  4801  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationID, labelKey).Return(nil, testErr).Once()
  4802  				return repo
  4803  			},
  4804  			InputApplicationID: applicationID,
  4805  			InputLabel:         label,
  4806  			ExpectedLabel:      nil,
  4807  			ExpectedErrMessage: testErr.Error(),
  4808  		},
  4809  		{
  4810  			Name: "Returns error when application doesn't exist",
  4811  			RepositoryFn: func() *automock.ApplicationRepository {
  4812  				repo := &automock.ApplicationRepository{}
  4813  				repo.On("Exists", ctx, tnt, applicationID).Return(false, testErr).Once()
  4814  
  4815  				return repo
  4816  			},
  4817  			LabelRepositoryFn:  UnusedLabelRepository,
  4818  			InputApplicationID: applicationID,
  4819  			InputLabel:         label,
  4820  			ExpectedErrMessage: testErr.Error(),
  4821  		},
  4822  	}
  4823  
  4824  	for _, testCase := range testCases {
  4825  		t.Run(testCase.Name, func(t *testing.T) {
  4826  			repo := testCase.RepositoryFn()
  4827  			labelRepo := testCase.LabelRepositoryFn()
  4828  			svc := application.NewService(nil, nil, repo, nil, nil, labelRepo, nil, nil, nil, nil, nil, "", nil)
  4829  
  4830  			// WHEN
  4831  			l, err := svc.GetLabel(ctx, testCase.InputApplicationID, testCase.InputLabel.Key)
  4832  
  4833  			// then
  4834  			if testCase.ExpectedErrMessage == "" {
  4835  				require.NoError(t, err)
  4836  				assert.Equal(t, l, testCase.ExpectedLabel)
  4837  			} else {
  4838  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  4839  			}
  4840  
  4841  			repo.AssertExpectations(t)
  4842  			labelRepo.AssertExpectations(t)
  4843  		})
  4844  	}
  4845  }
  4846  
  4847  func TestService_ListLabel(t *testing.T) {
  4848  	// GIVEN
  4849  	tnt := "tenant"
  4850  	externalTnt := "external-tnt"
  4851  
  4852  	ctx := context.TODO()
  4853  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  4854  
  4855  	testErr := errors.New("Test error")
  4856  
  4857  	applicationID := "foo"
  4858  	labelKey := "key"
  4859  	labelValue := []string{"value1"}
  4860  
  4861  	label := &model.LabelInput{
  4862  		Key:        labelKey,
  4863  		Value:      labelValue,
  4864  		ObjectID:   applicationID,
  4865  		ObjectType: model.ApplicationLabelableObject,
  4866  	}
  4867  
  4868  	modelLabel := &model.Label{
  4869  		ID:         "5d23d9d9-3d04-4fa9-95e6-d22e1ae62c11",
  4870  		Tenant:     str.Ptr(tnt),
  4871  		Key:        labelKey,
  4872  		Value:      labelValue,
  4873  		ObjectID:   applicationID,
  4874  		ObjectType: model.ApplicationLabelableObject,
  4875  	}
  4876  
  4877  	labels := map[string]*model.Label{"first": modelLabel, "second": modelLabel}
  4878  	testCases := []struct {
  4879  		Name               string
  4880  		RepositoryFn       func() *automock.ApplicationRepository
  4881  		LabelRepositoryFn  func() *automock.LabelRepository
  4882  		InputApplicationID string
  4883  		InputLabel         *model.LabelInput
  4884  		ExpectedOutput     map[string]*model.Label
  4885  		ExpectedErrMessage string
  4886  	}{
  4887  		{
  4888  			Name: "Success",
  4889  			RepositoryFn: func() *automock.ApplicationRepository {
  4890  				repo := &automock.ApplicationRepository{}
  4891  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4892  				return repo
  4893  			},
  4894  			LabelRepositoryFn: func() *automock.LabelRepository {
  4895  				repo := &automock.LabelRepository{}
  4896  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, applicationID).Return(labels, nil).Once()
  4897  				return repo
  4898  			},
  4899  			InputApplicationID: applicationID,
  4900  			InputLabel:         label,
  4901  			ExpectedOutput:     labels,
  4902  			ExpectedErrMessage: "",
  4903  		},
  4904  		{
  4905  			Name: "Returns error when labels receiving failed",
  4906  			RepositoryFn: func() *automock.ApplicationRepository {
  4907  				repo := &automock.ApplicationRepository{}
  4908  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4909  
  4910  				return repo
  4911  			},
  4912  			LabelRepositoryFn: func() *automock.LabelRepository {
  4913  				repo := &automock.LabelRepository{}
  4914  				repo.On("ListForObject", ctx, tnt, model.ApplicationLabelableObject, applicationID).Return(nil, testErr).Once()
  4915  				return repo
  4916  			},
  4917  			InputApplicationID: applicationID,
  4918  			InputLabel:         label,
  4919  			ExpectedOutput:     nil,
  4920  			ExpectedErrMessage: testErr.Error(),
  4921  		},
  4922  		{
  4923  			Name: "Returns error when application doesn't exist",
  4924  			RepositoryFn: func() *automock.ApplicationRepository {
  4925  				repo := &automock.ApplicationRepository{}
  4926  				repo.On("Exists", ctx, tnt, applicationID).Return(false, testErr).Once()
  4927  
  4928  				return repo
  4929  			},
  4930  			LabelRepositoryFn:  UnusedLabelRepository,
  4931  			InputApplicationID: applicationID,
  4932  			InputLabel:         label,
  4933  			ExpectedErrMessage: testErr.Error(),
  4934  		},
  4935  	}
  4936  
  4937  	for _, testCase := range testCases {
  4938  		t.Run(testCase.Name, func(t *testing.T) {
  4939  			repo := testCase.RepositoryFn()
  4940  			labelRepo := testCase.LabelRepositoryFn()
  4941  			svc := application.NewService(nil, nil, repo, nil, nil, labelRepo, nil, nil, nil, nil, nil, "", nil)
  4942  
  4943  			// WHEN
  4944  			l, err := svc.ListLabels(ctx, testCase.InputApplicationID)
  4945  
  4946  			// then
  4947  			if testCase.ExpectedErrMessage == "" {
  4948  				require.NoError(t, err)
  4949  				assert.Equal(t, l, testCase.ExpectedOutput)
  4950  			} else {
  4951  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  4952  			}
  4953  
  4954  			repo.AssertExpectations(t)
  4955  			labelRepo.AssertExpectations(t)
  4956  		})
  4957  	}
  4958  }
  4959  
  4960  func TestService_DeleteLabel(t *testing.T) {
  4961  	// GIVEN
  4962  	tnt := "tenant"
  4963  	externalTnt := "external-tnt"
  4964  
  4965  	ctx := context.TODO()
  4966  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  4967  
  4968  	testErr := errors.New("Test error")
  4969  
  4970  	applicationID := "foo"
  4971  
  4972  	labelKey := "key"
  4973  
  4974  	testCases := []struct {
  4975  		Name               string
  4976  		RepositoryFn       func() *automock.ApplicationRepository
  4977  		LabelRepositoryFn  func() *automock.LabelRepository
  4978  		FormationServiceFn func() *automock.FormationService
  4979  		InputApplicationID string
  4980  		InputKey           string
  4981  		ExpectedErrMessage string
  4982  	}{
  4983  		{
  4984  			Name: "Success",
  4985  			RepositoryFn: func() *automock.ApplicationRepository {
  4986  				repo := &automock.ApplicationRepository{}
  4987  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  4988  				return repo
  4989  			},
  4990  			LabelRepositoryFn: func() *automock.LabelRepository {
  4991  				repo := &automock.LabelRepository{}
  4992  				repo.On("Delete", ctx, tnt, model.ApplicationLabelableObject, applicationID, labelKey).Return(nil).Once()
  4993  				return repo
  4994  			},
  4995  			FormationServiceFn: UnusedFormationService,
  4996  			InputApplicationID: applicationID,
  4997  			InputKey:           labelKey,
  4998  			ExpectedErrMessage: "",
  4999  		},
  5000  		{
  5001  			Name: "Returns error when label delete failed",
  5002  			RepositoryFn: func() *automock.ApplicationRepository {
  5003  				repo := &automock.ApplicationRepository{}
  5004  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  5005  				return repo
  5006  			},
  5007  			LabelRepositoryFn: func() *automock.LabelRepository {
  5008  				repo := &automock.LabelRepository{}
  5009  				repo.On("Delete", ctx, tnt, model.ApplicationLabelableObject, applicationID, labelKey).Return(testErr).Once()
  5010  				return repo
  5011  			},
  5012  			FormationServiceFn: UnusedFormationService,
  5013  			InputApplicationID: applicationID,
  5014  			InputKey:           labelKey,
  5015  			ExpectedErrMessage: testErr.Error(),
  5016  		},
  5017  		{
  5018  			Name: "Returns error when application retrieval failed",
  5019  			RepositoryFn: func() *automock.ApplicationRepository {
  5020  				repo := &automock.ApplicationRepository{}
  5021  				repo.On("Exists", ctx, tnt, applicationID).Return(false, testErr).Once()
  5022  				return repo
  5023  			},
  5024  			LabelRepositoryFn:  UnusedLabelRepository,
  5025  			FormationServiceFn: UnusedFormationService,
  5026  			InputApplicationID: applicationID,
  5027  			InputKey:           labelKey,
  5028  			ExpectedErrMessage: testErr.Error(),
  5029  		},
  5030  		{
  5031  			Name: "Returns error when application does not exist",
  5032  			RepositoryFn: func() *automock.ApplicationRepository {
  5033  				repo := &automock.ApplicationRepository{}
  5034  				repo.On("Exists", ctx, tnt, applicationID).Return(false, nil).Once()
  5035  				return repo
  5036  			},
  5037  			LabelRepositoryFn:  UnusedLabelRepository,
  5038  			FormationServiceFn: UnusedFormationService,
  5039  			InputApplicationID: applicationID,
  5040  			InputKey:           labelKey,
  5041  			ExpectedErrMessage: fmt.Sprintf("application with ID %s doesn't exist", applicationID),
  5042  		},
  5043  		{
  5044  			Name: "Success when deleting formations from scenario label",
  5045  			RepositoryFn: func() *automock.ApplicationRepository {
  5046  				repo := &automock.ApplicationRepository{}
  5047  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  5048  				return repo
  5049  			},
  5050  			LabelRepositoryFn: func() *automock.LabelRepository {
  5051  				repo := &automock.LabelRepository{}
  5052  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationID, model.ScenariosKey).Return(&model.Label{Value: []interface{}{testScenario}}, nil).Once()
  5053  				return repo
  5054  			},
  5055  			FormationServiceFn: func() *automock.FormationService {
  5056  				service := &automock.FormationService{}
  5057  				service.On("UnassignFormation", ctx, tnt, applicationID, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, nil).Once()
  5058  				return service
  5059  			},
  5060  			InputApplicationID: applicationID,
  5061  			InputKey:           model.ScenariosKey,
  5062  			ExpectedErrMessage: "",
  5063  		},
  5064  		{
  5065  			Name: "Returns error when UnassignFormation fails",
  5066  			RepositoryFn: func() *automock.ApplicationRepository {
  5067  				repo := &automock.ApplicationRepository{}
  5068  				repo.On("Exists", ctx, tnt, applicationID).Return(true, nil).Once()
  5069  				return repo
  5070  			},
  5071  			LabelRepositoryFn: func() *automock.LabelRepository {
  5072  				repo := &automock.LabelRepository{}
  5073  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, applicationID, model.ScenariosKey).Return(&model.Label{Value: []interface{}{testScenario}}, nil).Once()
  5074  				return repo
  5075  			},
  5076  			FormationServiceFn: func() *automock.FormationService {
  5077  				service := &automock.FormationService{}
  5078  				service.On("UnassignFormation", ctx, tnt, applicationID, graphql.FormationObjectTypeApplication, model.Formation{Name: testScenario}).Return(nil, testErr).Once()
  5079  				return service
  5080  			},
  5081  			InputApplicationID: applicationID,
  5082  			InputKey:           model.ScenariosKey,
  5083  			ExpectedErrMessage: testErr.Error(),
  5084  		},
  5085  	}
  5086  
  5087  	for _, testCase := range testCases {
  5088  		t.Run(testCase.Name, func(t *testing.T) {
  5089  			repo := testCase.RepositoryFn()
  5090  			labelRepo := testCase.LabelRepositoryFn()
  5091  			formationSvc := testCase.FormationServiceFn()
  5092  			svc := application.NewService(nil, nil, repo, nil, nil, labelRepo, nil, nil, nil, nil, formationSvc, "", nil)
  5093  
  5094  			// WHEN
  5095  			err := svc.DeleteLabel(ctx, testCase.InputApplicationID, testCase.InputKey)
  5096  
  5097  			// then
  5098  			if testCase.ExpectedErrMessage == "" {
  5099  				require.NoError(t, err)
  5100  			} else {
  5101  				require.Error(t, err)
  5102  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
  5103  			}
  5104  
  5105  			repo.AssertExpectations(t)
  5106  		})
  5107  	}
  5108  }
  5109  
  5110  func TestService_GetBySystemNumber(t *testing.T) {
  5111  	tnt := "tenant"
  5112  	externalTnt := "external-tnt"
  5113  
  5114  	modelApp := fixModelApplication("foo", "tenant-foo", "foo", "Lorem Ipsum")
  5115  	ctx := context.TODO()
  5116  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
  5117  	testError := errors.New("Test error")
  5118  	systemNumber := "1"
  5119  
  5120  	testCases := []struct {
  5121  		Name              string
  5122  		RepositoryFn      func() *automock.ApplicationRepository
  5123  		InputSystemNumber string
  5124  		ExptectedValue    *model.Application
  5125  		ExpectedError     error
  5126  	}{
  5127  		{
  5128  			Name: "Application found",
  5129  			RepositoryFn: func() *automock.ApplicationRepository {
  5130  				repo := &automock.ApplicationRepository{}
  5131  				repo.On("GetBySystemNumber", ctx, tnt, systemNumber).Return(modelApp, nil)
  5132  				return repo
  5133  			},
  5134  			InputSystemNumber: systemNumber,
  5135  			ExptectedValue:    modelApp,
  5136  			ExpectedError:     nil,
  5137  		},
  5138  		{
  5139  			Name: "Returns error",
  5140  			RepositoryFn: func() *automock.ApplicationRepository {
  5141  				repo := &automock.ApplicationRepository{}
  5142  				repo.On("GetBySystemNumber", ctx, tnt, systemNumber).Return(nil, testError)
  5143  				return repo
  5144  			},
  5145  			InputSystemNumber: systemNumber,
  5146  			ExptectedValue:    nil,
  5147  			ExpectedError:     testError,
  5148  		},
  5149  	}
  5150  
  5151  	for _, testCase := range testCases {
  5152  		t.Run(testCase.Name, func(t *testing.T) {
  5153  			// GIVEN
  5154  			appRepo := testCase.RepositoryFn()
  5155  			svc := application.NewService(nil, nil, appRepo, nil, nil, nil, nil, nil, nil, nil, nil, "", nil)
  5156  
  5157  			// WHEN
  5158  			value, err := svc.GetBySystemNumber(ctx, testCase.InputSystemNumber)
  5159  
  5160  			// THEN
  5161  			if testCase.ExpectedError != nil {
  5162  				require.Error(t, err)
  5163  				assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
  5164  			} else {
  5165  				require.Nil(t, err)
  5166  			}
  5167  
  5168  			assert.Equal(t, testCase.ExptectedValue, value)
  5169  			appRepo.AssertExpectations(t)
  5170  		})
  5171  	}
  5172  }
  5173  
  5174  type testModel struct {
  5175  	ApplicationMatcherFn func(app *model.Application) bool
  5176  	Webhooks             []*model.Webhook
  5177  	APIs                 []*model.APIDefinition
  5178  	EventAPIs            []*model.EventDefinition
  5179  	Documents            []*model.Document
  5180  }
  5181  
  5182  type MatcherFunc func(app *model.Application) bool
  5183  
  5184  func modelFromInput(in model.ApplicationRegisterInput, tenant, applicationID string, applicationModelMatcherFn MatcherFunc) testModel {
  5185  	webhooksModel := make([]*model.Webhook, 0, len(in.Webhooks))
  5186  	for _, item := range in.Webhooks {
  5187  		webhooksModel = append(webhooksModel, item.ToWebhook(uuid.New().String(), applicationID, model.ApplicationWebhookReference))
  5188  	}
  5189  
  5190  	return testModel{
  5191  		ApplicationMatcherFn: applicationModelMatcherFn,
  5192  		Webhooks:             webhooksModel,
  5193  	}
  5194  }
  5195  
  5196  func convertToStringArray(t *testing.T, array []interface{}) []string {
  5197  	stringArray := make([]string, 0, len(array))
  5198  	for _, value := range array {
  5199  		convertedValue, ok := value.(string)
  5200  		require.True(t, ok, "Cannot convert array of interface{} to array of string in test method")
  5201  		stringArray = append(stringArray, convertedValue)
  5202  	}
  5203  	return stringArray
  5204  }
  5205  
  5206  func applicationMatcher(name string, description *string) func(app *model.Application) bool {
  5207  	return func(app *model.Application) bool {
  5208  		return app.Name == name && app.Description == description
  5209  	}
  5210  }
  5211  
  5212  func applicationFromTemplateMatcher(name string, description *string, appTemplateID *string) func(app *model.Application) bool {
  5213  	return func(app *model.Application) bool {
  5214  		return applicationMatcher(name, description)(app) && app.ApplicationTemplateID == appTemplateID
  5215  	}
  5216  }
  5217  
  5218  func applicationRegisterInputWithScenarios() model.ApplicationRegisterInput {
  5219  	return model.ApplicationRegisterInput{
  5220  		Name:    "foo.bar-not",
  5221  		BaseURL: str.Ptr("http://test.com"),
  5222  		Webhooks: []*model.WebhookInput{
  5223  			{URL: stringPtr("test.foo.com")},
  5224  			{URL: stringPtr("test.bar.com")},
  5225  		},
  5226  		Labels: map[string]interface{}{
  5227  			"label":                "value",
  5228  			"applicationType":      "test-app-with-ppms",
  5229  			"ppmsProductVersionId": "1",
  5230  			model.ScenariosKey:     []interface{}{testScenario},
  5231  		},
  5232  		IntegrationSystemID: &intSysID,
  5233  		Bundles: []*model.BundleCreateInput{
  5234  			{
  5235  				Name: "bndl1",
  5236  				APIDefinitions: []*model.APIDefinitionInput{
  5237  					{
  5238  						Name: "foo",
  5239  					},
  5240  					{
  5241  						Name: "bar",
  5242  					},
  5243  				},
  5244  				APISpecs: []*model.SpecInput{
  5245  					{
  5246  						FetchRequest: &model.FetchRequestInput{URL: "api.foo.bar"},
  5247  					},
  5248  					nil,
  5249  				},
  5250  				EventDefinitions: []*model.EventDefinitionInput{
  5251  					{
  5252  						Name: "foo",
  5253  					},
  5254  					{
  5255  						Name: "bar",
  5256  					},
  5257  				},
  5258  				EventSpecs: []*model.SpecInput{
  5259  					{
  5260  						FetchRequest: &model.FetchRequestInput{URL: "eventapi.foo.bar"},
  5261  					},
  5262  					nil,
  5263  				},
  5264  				Documents: []*model.DocumentInput{
  5265  					{Title: "foo", Description: "test", FetchRequest: &model.FetchRequestInput{URL: "doc.foo.bar"}},
  5266  					{Title: "bar", Description: "test"},
  5267  				},
  5268  			},
  5269  		},
  5270  	}
  5271  }
  5272  
  5273  func UnusedLabelService() *automock.LabelService {
  5274  	return &automock.LabelService{}
  5275  }
  5276  func UnusedBundleService() *automock.BundleService {
  5277  	return &automock.BundleService{}
  5278  }
  5279  func UnusedUIDService() *automock.UIDService {
  5280  	return &automock.UIDService{}
  5281  }
  5282  
  5283  func UnusedFormationService() *automock.FormationService {
  5284  	return &automock.FormationService{}
  5285  }
  5286  
  5287  func UnusedWebhookRepository() *automock.WebhookRepository {
  5288  	return &automock.WebhookRepository{}
  5289  }
  5290  
  5291  func UnusedIntegrationSystemRepository() *automock.IntegrationSystemRepository {
  5292  	return &automock.IntegrationSystemRepository{}
  5293  }
  5294  
  5295  func UnusedLabelRepository() *automock.LabelRepository {
  5296  	return &automock.LabelRepository{}
  5297  }
  5298  
  5299  func UnusedApplicationRepository() *automock.ApplicationRepository {
  5300  	return &automock.ApplicationRepository{}
  5301  }
  5302  
  5303  func UnusedLabelUpsertService() *automock.LabelService {
  5304  	return &automock.LabelService{}
  5305  }