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

     1  package label_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/kyma-incubator/compass/components/director/internal/domain/label/lbltest"
     8  
     9  	"github.com/kyma-incubator/compass/components/director/pkg/str"
    10  
    11  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    12  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    13  
    14  	"github.com/kyma-incubator/compass/components/director/internal/domain/labeldef"
    15  
    16  	"github.com/kyma-incubator/compass/components/director/internal/domain/label"
    17  	"github.com/kyma-incubator/compass/components/director/internal/domain/label/automock"
    18  	"github.com/kyma-incubator/compass/components/director/internal/domain/tenant"
    19  	"github.com/kyma-incubator/compass/components/director/internal/model"
    20  	"github.com/pkg/errors"
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/require"
    23  )
    24  
    25  var testScenario = "test-scenario"
    26  
    27  func TestLabelService_UpsertMultipleLabels(t *testing.T) {
    28  	// GIVEN
    29  	tnt := tenantID
    30  	externalTnt := "external-tenant"
    31  	ctx := context.TODO()
    32  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
    33  	id := "foo"
    34  
    35  	notFoundErr := errors.New("Label not found")
    36  	testErr := errors.New("Test error")
    37  
    38  	runtimeType := model.RuntimeLabelableObject
    39  	runtimeID := "bar"
    40  
    41  	stringValue := "lorem ipsum"
    42  	arrayValue := []interface{}{"foo", "bar"}
    43  	objectValue := map[string]interface{}{
    44  		"foo": "bar",
    45  	}
    46  
    47  	testCases := []struct {
    48  		Name           string
    49  		LabelRepoFn    func() *automock.LabelRepository
    50  		LabelDefRepoFn func() *automock.LabelDefinitionRepository
    51  		UIDServiceFn   func() *automock.UIDService
    52  
    53  		InputObjectType model.LabelableObject
    54  		InputObjectID   string
    55  		InputLabels     map[string]interface{}
    56  
    57  		ExpectedErrMessage string
    58  	}{
    59  		{
    60  			Name: "Success",
    61  			InputLabels: map[string]interface{}{
    62  				"string": stringValue,
    63  				"array":  arrayValue,
    64  				"object": objectValue,
    65  			},
    66  			InputObjectID:   runtimeID,
    67  			InputObjectType: runtimeType,
    68  			LabelRepoFn: func() *automock.LabelRepository {
    69  				repo := &automock.LabelRepository{}
    70  				repo.On("Upsert", ctx, tenantID, &model.Label{
    71  					ID: id, ObjectType: runtimeType, ObjectID: runtimeID, Key: "object", Value: objectValue,
    72  				}).Return(nil).Once()
    73  				repo.On("Upsert", ctx, tenantID, &model.Label{
    74  					ID: id, ObjectType: runtimeType, ObjectID: runtimeID, Key: "string", Value: stringValue,
    75  				}).Return(nil).Once()
    76  				repo.On("Upsert", ctx, tenantID, &model.Label{
    77  					ID: id, ObjectType: runtimeType, ObjectID: runtimeID, Key: "array", Value: arrayValue,
    78  				}).Return(nil).Once()
    79  				return repo
    80  			},
    81  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
    82  				return &automock.LabelDefinitionRepository{}
    83  			},
    84  			UIDServiceFn: func() *automock.UIDService {
    85  				svc := &automock.UIDService{}
    86  				svc.On("Generate").Return(id)
    87  				return svc
    88  			},
    89  
    90  			ExpectedErrMessage: "",
    91  		},
    92  		{
    93  			Name: "Error",
    94  			InputLabels: map[string]interface{}{
    95  				"object": objectValue,
    96  				"string": stringValue,
    97  			},
    98  			InputObjectID:   runtimeID,
    99  			InputObjectType: runtimeType,
   100  			LabelRepoFn: func() *automock.LabelRepository {
   101  				repo := &automock.LabelRepository{}
   102  				repo.On("GetByKey", ctx, tnt, runtimeType, runtimeID, "object").Return(nil, notFoundErr).Maybe()
   103  				repo.On("GetByKey", ctx, tnt, runtimeType, runtimeID, "string").Return(nil, notFoundErr).Maybe()
   104  
   105  				repo.On("Upsert", ctx, tenantID, &model.Label{
   106  					ID: id, ObjectType: runtimeType, ObjectID: runtimeID, Key: "object", Value: objectValue,
   107  				}).Return(testErr).Maybe()
   108  				repo.On("Upsert", ctx, tenantID, &model.Label{
   109  					ID: id, ObjectType: runtimeType, ObjectID: runtimeID, Key: "string", Value: stringValue,
   110  				}).Return(nil).Maybe()
   111  				return repo
   112  			},
   113  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   114  				return &automock.LabelDefinitionRepository{}
   115  			},
   116  			UIDServiceFn: func() *automock.UIDService {
   117  				svc := &automock.UIDService{}
   118  				svc.On("Generate").Return(id)
   119  				return svc
   120  			},
   121  
   122  			ExpectedErrMessage: testErr.Error(),
   123  		},
   124  	}
   125  
   126  	for _, testCase := range testCases {
   127  		t.Run(testCase.Name, func(t *testing.T) {
   128  			labelRepo := testCase.LabelRepoFn()
   129  			labelDefRepo := testCase.LabelDefRepoFn()
   130  			uidService := testCase.UIDServiceFn()
   131  
   132  			svc := label.NewLabelService(labelRepo, labelDefRepo, uidService)
   133  
   134  			// WHEN
   135  			err := svc.UpsertMultipleLabels(ctx, tnt, testCase.InputObjectType, testCase.InputObjectID, testCase.InputLabels)
   136  
   137  			// THEN
   138  			if testCase.ExpectedErrMessage == "" {
   139  				require.NoError(t, err)
   140  			} else {
   141  				require.Error(t, err)
   142  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   143  			}
   144  
   145  			labelRepo.AssertExpectations(t)
   146  			labelDefRepo.AssertExpectations(t)
   147  			uidService.AssertExpectations(t)
   148  		})
   149  	}
   150  }
   151  
   152  func TestLabelService_UpsertLabel(t *testing.T) {
   153  	// GIVEN
   154  	tnt := tenantID
   155  	externalTnt := "external-tenant"
   156  	ctx := context.TODO()
   157  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
   158  	id := "foo"
   159  	version := 0
   160  	scenarioSchema, err := labeldef.NewSchemaForFormations([]string{testScenario})
   161  	assert.NoError(t, err)
   162  	scenarioLabelDefinition := &model.LabelDefinition{
   163  		Key:     model.ScenariosKey,
   164  		Tenant:  tnt,
   165  		ID:      "foo",
   166  		Schema:  &scenarioSchema,
   167  		Version: version,
   168  	}
   169  
   170  	testErr := errors.New("Test error")
   171  
   172  	testCases := []struct {
   173  		Name           string
   174  		LabelRepoFn    func() *automock.LabelRepository
   175  		LabelDefRepoFn func() *automock.LabelDefinitionRepository
   176  		UIDServiceFn   func() *automock.UIDService
   177  
   178  		LabelInput *model.LabelInput
   179  
   180  		ExpectedErrMessage string
   181  	}{
   182  		{
   183  			Name: "Success - No LabelDefinition",
   184  			LabelInput: &model.LabelInput{
   185  				Key:        "test",
   186  				Value:      "string",
   187  				ObjectType: model.ApplicationLabelableObject,
   188  				ObjectID:   "appID",
   189  				Version:    version,
   190  			},
   191  			LabelRepoFn: func() *automock.LabelRepository {
   192  				repo := &automock.LabelRepository{}
   193  				repo.On("Upsert", ctx, tenantID, &model.Label{
   194  					Key:        "test",
   195  					Value:      "string",
   196  					ObjectType: model.ApplicationLabelableObject,
   197  					ObjectID:   "appID",
   198  					ID:         id,
   199  					Version:    version,
   200  				}).Return(nil).Once()
   201  				return repo
   202  			},
   203  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   204  				return &automock.LabelDefinitionRepository{}
   205  			},
   206  			UIDServiceFn: func() *automock.UIDService {
   207  				svc := &automock.UIDService{}
   208  				svc.On("Generate").Return(id)
   209  				return svc
   210  			},
   211  			ExpectedErrMessage: "",
   212  		},
   213  		{
   214  			Name: "Success - No scenario LabelDefinition",
   215  			LabelInput: &model.LabelInput{
   216  				Key:        model.ScenariosKey,
   217  				Value:      []string{testScenario},
   218  				ObjectType: model.ApplicationLabelableObject,
   219  				ObjectID:   "appID",
   220  				Version:    version,
   221  			},
   222  			LabelRepoFn: func() *automock.LabelRepository {
   223  				return &automock.LabelRepository{}
   224  			},
   225  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   226  				repo := &automock.LabelDefinitionRepository{}
   227  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(nil, apperrors.NewNotFoundError(resource.LabelDefinition, "")).Once()
   228  				return repo
   229  			},
   230  			UIDServiceFn:       lbltest.UnusedUUIDService(),
   231  			ExpectedErrMessage: "while getting LabelDefinition",
   232  		},
   233  		{
   234  			Name: "Success - scenario LabelDefinition exists",
   235  			LabelInput: &model.LabelInput{
   236  				Key:        model.ScenariosKey,
   237  				Value:      []string{testScenario},
   238  				ObjectType: model.ApplicationLabelableObject,
   239  				ObjectID:   "appID",
   240  				Version:    version,
   241  			},
   242  			LabelRepoFn: func() *automock.LabelRepository {
   243  				repo := &automock.LabelRepository{}
   244  				repo.On("Upsert", ctx, tenantID, &model.Label{
   245  					Key:        model.ScenariosKey,
   246  					Tenant:     str.Ptr(tenantID),
   247  					Value:      []string{testScenario},
   248  					ObjectType: model.ApplicationLabelableObject,
   249  					ObjectID:   "appID",
   250  					ID:         id,
   251  					Version:    version,
   252  				}).Return(nil).Once()
   253  				return repo
   254  			},
   255  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   256  				repo := &automock.LabelDefinitionRepository{}
   257  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(scenarioLabelDefinition, nil).Once()
   258  				return repo
   259  			},
   260  			UIDServiceFn: func() *automock.UIDService {
   261  				svc := &automock.UIDService{}
   262  				svc.On("Generate").Return(id)
   263  				return svc
   264  			},
   265  			ExpectedErrMessage: "",
   266  		},
   267  		{
   268  			Name: "Error - Validate value",
   269  			LabelInput: &model.LabelInput{
   270  				Key:        model.ScenariosKey,
   271  				Value:      []string{"test"},
   272  				ObjectType: model.ApplicationLabelableObject,
   273  				ObjectID:   "appID",
   274  				Version:    version,
   275  			},
   276  			LabelRepoFn: func() *automock.LabelRepository {
   277  				repo := &automock.LabelRepository{}
   278  				return repo
   279  			},
   280  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   281  				repo := &automock.LabelDefinitionRepository{}
   282  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(scenarioLabelDefinition, nil).Once()
   283  				return repo
   284  			},
   285  			UIDServiceFn: func() *automock.UIDService {
   286  				svc := &automock.UIDService{}
   287  				return svc
   288  			},
   289  			ExpectedErrMessage: "is not valid against JSON Schema",
   290  		},
   291  		{
   292  			Name: "Error - Getting scenario LabelDefinition",
   293  			LabelInput: &model.LabelInput{
   294  				Key:        model.ScenariosKey,
   295  				Value:      []string{testScenario},
   296  				ObjectType: model.ApplicationLabelableObject,
   297  				ObjectID:   "appID",
   298  				Version:    version,
   299  			},
   300  			LabelRepoFn: func() *automock.LabelRepository {
   301  				repo := &automock.LabelRepository{}
   302  				return repo
   303  			},
   304  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   305  				repo := &automock.LabelDefinitionRepository{}
   306  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(nil, testErr).Once()
   307  				return repo
   308  			},
   309  			UIDServiceFn:       lbltest.UnusedUUIDService(),
   310  			ExpectedErrMessage: "Test error",
   311  		},
   312  		{
   313  			Name: "Error - Upserting scenario label",
   314  			LabelInput: &model.LabelInput{
   315  				Key:        model.ScenariosKey,
   316  				Value:      []string{testScenario},
   317  				ObjectType: model.ApplicationLabelableObject,
   318  				ObjectID:   "appID",
   319  				Version:    version,
   320  			},
   321  			LabelRepoFn: func() *automock.LabelRepository {
   322  				repo := &automock.LabelRepository{}
   323  				repo.On("Upsert", ctx, tenantID, &model.Label{
   324  					Key:        model.ScenariosKey,
   325  					Tenant:     str.Ptr(tenantID),
   326  					Value:      []string{testScenario},
   327  					ObjectType: model.ApplicationLabelableObject,
   328  					ObjectID:   "appID",
   329  					ID:         id,
   330  					Version:    version,
   331  				}).Return(testErr).Once()
   332  				return repo
   333  			},
   334  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   335  				repo := &automock.LabelDefinitionRepository{}
   336  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(nil, nil).Once()
   337  				return repo
   338  			},
   339  			UIDServiceFn: func() *automock.UIDService {
   340  				svc := &automock.UIDService{}
   341  				svc.On("Generate").Return(id)
   342  				return svc
   343  			},
   344  			ExpectedErrMessage: "Test error",
   345  		},
   346  	}
   347  
   348  	for _, testCase := range testCases {
   349  		t.Run(testCase.Name, func(t *testing.T) {
   350  			labelRepo := testCase.LabelRepoFn()
   351  			labelDefRepo := testCase.LabelDefRepoFn()
   352  			uidService := testCase.UIDServiceFn()
   353  
   354  			svc := label.NewLabelService(labelRepo, labelDefRepo, uidService)
   355  
   356  			// WHEN
   357  			err := svc.UpsertLabel(ctx, tnt, testCase.LabelInput)
   358  
   359  			// THEN
   360  			if testCase.ExpectedErrMessage == "" {
   361  				require.NoError(t, err)
   362  			} else {
   363  				require.Error(t, err)
   364  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   365  			}
   366  
   367  			labelRepo.AssertExpectations(t)
   368  			labelDefRepo.AssertExpectations(t)
   369  			uidService.AssertExpectations(t)
   370  		})
   371  	}
   372  }
   373  
   374  func TestLabelService_UpsertLabelGlobal(t *testing.T) {
   375  	// GIVEN
   376  	ctx := context.TODO()
   377  
   378  	id := "foo"
   379  	version := 0
   380  
   381  	testErr := errors.New("Test error")
   382  
   383  	testCases := []struct {
   384  		Name         string
   385  		LabelRepoFn  func() *automock.LabelRepository
   386  		UIDServiceFn func() *automock.UIDService
   387  
   388  		LabelInput *model.LabelInput
   389  
   390  		ExpectedErrMessage string
   391  	}{
   392  		{
   393  			Name: "Success",
   394  			LabelInput: &model.LabelInput{
   395  				Key:        "test",
   396  				Value:      "string",
   397  				ObjectType: model.ApplicationLabelableObject,
   398  				ObjectID:   "appID",
   399  				Version:    version,
   400  			},
   401  			LabelRepoFn: func() *automock.LabelRepository {
   402  				repo := &automock.LabelRepository{}
   403  				repo.On("UpsertGlobal", ctx, &model.Label{
   404  					Key:        "test",
   405  					Value:      "string",
   406  					ObjectType: model.ApplicationLabelableObject,
   407  					ObjectID:   "appID",
   408  					ID:         id,
   409  					Version:    version,
   410  				}).Return(nil).Once()
   411  				return repo
   412  			},
   413  			UIDServiceFn: func() *automock.UIDService {
   414  				svc := &automock.UIDService{}
   415  				svc.On("Generate").Return(id)
   416  				return svc
   417  			},
   418  			ExpectedErrMessage: "",
   419  		},
   420  
   421  		{
   422  			Name: "Error when upserting label",
   423  			LabelInput: &model.LabelInput{
   424  				Key:        "test",
   425  				Value:      "string",
   426  				ObjectType: model.ApplicationLabelableObject,
   427  				ObjectID:   "appID",
   428  				Version:    version,
   429  			},
   430  			LabelRepoFn: func() *automock.LabelRepository {
   431  				repo := &automock.LabelRepository{}
   432  				repo.On("UpsertGlobal", ctx, &model.Label{
   433  					Key:        "test",
   434  					Value:      "string",
   435  					ObjectType: model.ApplicationLabelableObject,
   436  					ObjectID:   "appID",
   437  					ID:         id,
   438  					Version:    version,
   439  				}).Return(testErr).Once()
   440  				return repo
   441  			},
   442  			UIDServiceFn: func() *automock.UIDService {
   443  				svc := &automock.UIDService{}
   444  				svc.On("Generate").Return(id)
   445  				return svc
   446  			},
   447  			ExpectedErrMessage: testErr.Error(),
   448  		},
   449  	}
   450  
   451  	for _, testCase := range testCases {
   452  		t.Run(testCase.Name, func(t *testing.T) {
   453  			labelRepo := testCase.LabelRepoFn()
   454  			uidService := testCase.UIDServiceFn()
   455  
   456  			svc := label.NewLabelService(labelRepo, nil, uidService)
   457  
   458  			// WHEN
   459  			err := svc.UpsertLabelGlobal(ctx, testCase.LabelInput)
   460  
   461  			// THEN
   462  			if testCase.ExpectedErrMessage == "" {
   463  				require.NoError(t, err)
   464  			} else {
   465  				require.Error(t, err)
   466  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   467  			}
   468  
   469  			labelRepo.AssertExpectations(t)
   470  			uidService.AssertExpectations(t)
   471  		})
   472  	}
   473  }
   474  
   475  func TestLabelService_CreateLabel(t *testing.T) {
   476  	// GIVEN
   477  	tnt := tenantID
   478  	externalTnt := "external-tenant"
   479  	ctx := context.TODO()
   480  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
   481  	id := "foo"
   482  	version := 0
   483  	scenarioSchema, err := labeldef.NewSchemaForFormations([]string{testScenario})
   484  	assert.NoError(t, err)
   485  	scenarioLabelDefinition := &model.LabelDefinition{
   486  		Key:     model.ScenariosKey,
   487  		Tenant:  tnt,
   488  		ID:      "foo",
   489  		Schema:  &scenarioSchema,
   490  		Version: version,
   491  	}
   492  
   493  	testErr := errors.New("Test error")
   494  
   495  	testCases := []struct {
   496  		Name           string
   497  		LabelRepoFn    func() *automock.LabelRepository
   498  		LabelDefRepoFn func() *automock.LabelDefinitionRepository
   499  		UIDServiceFn   func() *automock.UIDService
   500  
   501  		LabelInput *model.LabelInput
   502  
   503  		ExpectedErrMessage string
   504  	}{
   505  		{
   506  			Name: "Success - Not a scenarios key",
   507  			LabelInput: &model.LabelInput{
   508  				Key:        "test",
   509  				Value:      "string",
   510  				ObjectType: model.ApplicationLabelableObject,
   511  				ObjectID:   "appID",
   512  				Version:    version,
   513  			},
   514  			LabelRepoFn: func() *automock.LabelRepository {
   515  				repo := &automock.LabelRepository{}
   516  				repo.On("Create", ctx, tenantID, &model.Label{
   517  					Key:        "test",
   518  					Value:      "string",
   519  					ObjectType: model.ApplicationLabelableObject,
   520  					ObjectID:   "appID",
   521  					ID:         id,
   522  					Version:    version,
   523  				}).Return(nil).Once()
   524  				return repo
   525  			},
   526  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   527  				return &automock.LabelDefinitionRepository{}
   528  			},
   529  			UIDServiceFn:       lbltest.UnusedUUIDService(),
   530  			ExpectedErrMessage: "",
   531  		},
   532  		{
   533  			Name: "Success - scenario LabelDefinition exists",
   534  			LabelInput: &model.LabelInput{
   535  				Key:        model.ScenariosKey,
   536  				Value:      []string{testScenario},
   537  				ObjectType: model.ApplicationLabelableObject,
   538  				ObjectID:   "appID",
   539  				Version:    version,
   540  			},
   541  			LabelRepoFn: func() *automock.LabelRepository {
   542  				repo := &automock.LabelRepository{}
   543  				repo.On("Create", ctx, tenantID, &model.Label{
   544  					Key:        model.ScenariosKey,
   545  					Tenant:     str.Ptr(tenantID),
   546  					Value:      []string{testScenario},
   547  					ObjectType: model.ApplicationLabelableObject,
   548  					ObjectID:   "appID",
   549  					ID:         id,
   550  					Version:    version,
   551  				}).Return(nil).Once()
   552  				return repo
   553  			},
   554  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   555  				repo := &automock.LabelDefinitionRepository{}
   556  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(scenarioLabelDefinition, nil).Once()
   557  				return repo
   558  			},
   559  			UIDServiceFn: func() *automock.UIDService {
   560  				svc := &automock.UIDService{}
   561  				return svc
   562  			},
   563  			ExpectedErrMessage: "",
   564  		},
   565  		{
   566  			Name: "Error - scenario labelInput is not valid against schema",
   567  			LabelInput: &model.LabelInput{
   568  				Key:        model.ScenariosKey,
   569  				Value:      []string{"test"},
   570  				ObjectType: model.ApplicationLabelableObject,
   571  				ObjectID:   "appID",
   572  				Version:    version,
   573  			},
   574  			LabelRepoFn: func() *automock.LabelRepository {
   575  				repo := &automock.LabelRepository{}
   576  				return repo
   577  			},
   578  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   579  				repo := &automock.LabelDefinitionRepository{}
   580  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(scenarioLabelDefinition, nil).Once()
   581  				return repo
   582  			},
   583  			UIDServiceFn: func() *automock.UIDService {
   584  				svc := &automock.UIDService{}
   585  				return svc
   586  			},
   587  			ExpectedErrMessage: "is not valid against JSON Schema",
   588  		},
   589  		{
   590  			Name: "Error - Creating new Label",
   591  			LabelInput: &model.LabelInput{
   592  				Key:        model.ScenariosKey,
   593  				Value:      []string{testScenario},
   594  				ObjectType: model.ApplicationLabelableObject,
   595  				ObjectID:   "appID",
   596  				Version:    version,
   597  			},
   598  			LabelRepoFn: func() *automock.LabelRepository {
   599  				repo := &automock.LabelRepository{}
   600  				repo.On("Create", ctx, tenantID, &model.Label{
   601  					Key:        model.ScenariosKey,
   602  					Tenant:     str.Ptr(tenantID),
   603  					Value:      []string{testScenario},
   604  					ObjectType: model.ApplicationLabelableObject,
   605  					ObjectID:   "appID",
   606  					ID:         id,
   607  					Version:    version,
   608  				}).Return(testErr)
   609  				return repo
   610  			},
   611  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   612  				repo := &automock.LabelDefinitionRepository{}
   613  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(nil, nil).Once()
   614  				return repo
   615  			},
   616  			UIDServiceFn:       lbltest.UnusedUUIDService(),
   617  			ExpectedErrMessage: "Test error",
   618  		},
   619  		{
   620  			Name: "Error while reading LabelDefinition value",
   621  			LabelInput: &model.LabelInput{
   622  				Key:        model.ScenariosKey,
   623  				Value:      []string{testScenario},
   624  				ObjectType: model.ApplicationLabelableObject,
   625  				ObjectID:   "appID",
   626  				Version:    version,
   627  			},
   628  			LabelRepoFn: func() *automock.LabelRepository {
   629  				repo := &automock.LabelRepository{}
   630  				return repo
   631  			},
   632  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   633  				repo := &automock.LabelDefinitionRepository{}
   634  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(nil, testErr).Once()
   635  				return repo
   636  			},
   637  			UIDServiceFn:       lbltest.UnusedUUIDService(),
   638  			ExpectedErrMessage: "while getting LabelDefinition",
   639  		},
   640  	}
   641  
   642  	for _, testCase := range testCases {
   643  		t.Run(testCase.Name, func(t *testing.T) {
   644  			labelRepo := testCase.LabelRepoFn()
   645  			labelDefRepo := testCase.LabelDefRepoFn()
   646  			uidService := testCase.UIDServiceFn()
   647  
   648  			svc := label.NewLabelService(labelRepo, labelDefRepo, uidService)
   649  
   650  			// WHEN
   651  			err := svc.CreateLabel(ctx, tnt, id, testCase.LabelInput)
   652  
   653  			// then
   654  			if testCase.ExpectedErrMessage == "" {
   655  				require.NoError(t, err)
   656  			} else {
   657  				require.Error(t, err)
   658  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   659  			}
   660  
   661  			labelRepo.AssertExpectations(t)
   662  			labelDefRepo.AssertExpectations(t)
   663  			uidService.AssertExpectations(t)
   664  		})
   665  	}
   666  }
   667  
   668  func TestLabelService_UpdateLabel(t *testing.T) {
   669  	// GIVEN
   670  	tnt := tenantID
   671  	externalTnt := "external-tenant"
   672  	ctx := context.TODO()
   673  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
   674  	id := "foo"
   675  	version := 0
   676  	scenarioSchema, err := labeldef.NewSchemaForFormations([]string{testScenario})
   677  	assert.NoError(t, err)
   678  	scenarioLabelDefinition := &model.LabelDefinition{
   679  		Key:     model.ScenariosKey,
   680  		Tenant:  tnt,
   681  		ID:      "foo",
   682  		Schema:  &scenarioSchema,
   683  		Version: version,
   684  	}
   685  
   686  	testErr := errors.New("Test error")
   687  
   688  	testCases := []struct {
   689  		Name           string
   690  		LabelRepoFn    func() *automock.LabelRepository
   691  		LabelDefRepoFn func() *automock.LabelDefinitionRepository
   692  		UIDServiceFn   func() *automock.UIDService
   693  
   694  		LabelInput *model.LabelInput
   695  
   696  		ExpectedErrMessage string
   697  	}{
   698  		{
   699  			Name: "Success - Not a scenarios key",
   700  			LabelInput: &model.LabelInput{
   701  				Key:        "test",
   702  				Value:      "string",
   703  				ObjectType: model.ApplicationLabelableObject,
   704  				ObjectID:   "appID",
   705  				Version:    version,
   706  			},
   707  			LabelRepoFn: func() *automock.LabelRepository {
   708  				repo := &automock.LabelRepository{}
   709  				repo.On("UpdateWithVersion", ctx, tenantID, &model.Label{
   710  					Key:        "test",
   711  					Value:      "string",
   712  					ObjectType: model.ApplicationLabelableObject,
   713  					ObjectID:   "appID",
   714  					ID:         id,
   715  					Version:    version,
   716  				}).Return(nil).Once()
   717  				return repo
   718  			},
   719  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   720  				return &automock.LabelDefinitionRepository{}
   721  			},
   722  			UIDServiceFn:       lbltest.UnusedUUIDService(),
   723  			ExpectedErrMessage: "",
   724  		},
   725  		{
   726  			Name: "Success - scenario LabelDefinition exists",
   727  			LabelInput: &model.LabelInput{
   728  				Key:        model.ScenariosKey,
   729  				Value:      []string{testScenario},
   730  				ObjectType: model.ApplicationLabelableObject,
   731  				ObjectID:   "appID",
   732  				Version:    version,
   733  			},
   734  			LabelRepoFn: func() *automock.LabelRepository {
   735  				repo := &automock.LabelRepository{}
   736  				repo.On("UpdateWithVersion", ctx, tenantID, &model.Label{
   737  					Key:        model.ScenariosKey,
   738  					Tenant:     str.Ptr(tenantID),
   739  					Value:      []string{testScenario},
   740  					ObjectType: model.ApplicationLabelableObject,
   741  					ObjectID:   "appID",
   742  					ID:         id,
   743  					Version:    version,
   744  				}).Return(nil).Once()
   745  				return repo
   746  			},
   747  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   748  				repo := &automock.LabelDefinitionRepository{}
   749  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(scenarioLabelDefinition, nil).Once()
   750  				return repo
   751  			},
   752  			UIDServiceFn: func() *automock.UIDService {
   753  				svc := &automock.UIDService{}
   754  				return svc
   755  			},
   756  			ExpectedErrMessage: "",
   757  		},
   758  		{
   759  			Name: "Error - labelInput is not valid against schema",
   760  			LabelInput: &model.LabelInput{
   761  				Key:        model.ScenariosKey,
   762  				Value:      []string{"TEST"},
   763  				ObjectType: model.ApplicationLabelableObject,
   764  				ObjectID:   "appID",
   765  				Version:    version,
   766  			},
   767  			LabelRepoFn: func() *automock.LabelRepository {
   768  				repo := &automock.LabelRepository{}
   769  				return repo
   770  			},
   771  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   772  				repo := &automock.LabelDefinitionRepository{}
   773  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(scenarioLabelDefinition, nil).Once()
   774  				return repo
   775  			},
   776  			UIDServiceFn: func() *automock.UIDService {
   777  				svc := &automock.UIDService{}
   778  				return svc
   779  			},
   780  			ExpectedErrMessage: "is not valid against JSON Schema",
   781  		},
   782  		{
   783  			Name: "Error - Updating Label",
   784  			LabelInput: &model.LabelInput{
   785  				Key:        model.ScenariosKey,
   786  				Value:      []string{testScenario},
   787  				ObjectType: model.ApplicationLabelableObject,
   788  				ObjectID:   "appID",
   789  				Version:    version,
   790  			},
   791  			LabelRepoFn: func() *automock.LabelRepository {
   792  				repo := &automock.LabelRepository{}
   793  				repo.On("UpdateWithVersion", ctx, tenantID, &model.Label{
   794  					Key:        model.ScenariosKey,
   795  					Tenant:     str.Ptr(tenantID),
   796  					Value:      []string{testScenario},
   797  					ObjectType: model.ApplicationLabelableObject,
   798  					ObjectID:   "appID",
   799  					ID:         id,
   800  					Version:    version,
   801  				}).Return(testErr)
   802  				return repo
   803  			},
   804  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   805  				repo := &automock.LabelDefinitionRepository{}
   806  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(nil, nil).Once()
   807  				return repo
   808  			},
   809  			UIDServiceFn:       lbltest.UnusedUUIDService(),
   810  			ExpectedErrMessage: "Test error",
   811  		},
   812  		{
   813  			Name: "Error while reading LabelDefinition value",
   814  			LabelInput: &model.LabelInput{
   815  				Key:        model.ScenariosKey,
   816  				Value:      []string{testScenario},
   817  				ObjectType: model.ApplicationLabelableObject,
   818  				ObjectID:   "appID",
   819  				Version:    version,
   820  			},
   821  			LabelRepoFn: func() *automock.LabelRepository {
   822  				repo := &automock.LabelRepository{}
   823  				return repo
   824  			},
   825  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   826  				repo := &automock.LabelDefinitionRepository{}
   827  				repo.On("GetByKey", ctx, tnt, model.ScenariosKey).Return(nil, testErr).Once()
   828  				return repo
   829  			},
   830  			UIDServiceFn:       lbltest.UnusedUUIDService(),
   831  			ExpectedErrMessage: "while getting LabelDefinition",
   832  		},
   833  	}
   834  
   835  	for _, testCase := range testCases {
   836  		t.Run(testCase.Name, func(t *testing.T) {
   837  			labelRepo := testCase.LabelRepoFn()
   838  			labelDefRepo := testCase.LabelDefRepoFn()
   839  			uidService := testCase.UIDServiceFn()
   840  
   841  			svc := label.NewLabelService(labelRepo, labelDefRepo, uidService)
   842  
   843  			// WHEN
   844  			err := svc.UpdateLabel(ctx, tnt, id, testCase.LabelInput)
   845  
   846  			// then
   847  			if testCase.ExpectedErrMessage == "" {
   848  				require.NoError(t, err)
   849  			} else {
   850  				require.Error(t, err)
   851  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   852  			}
   853  
   854  			labelRepo.AssertExpectations(t)
   855  			labelDefRepo.AssertExpectations(t)
   856  			uidService.AssertExpectations(t)
   857  		})
   858  	}
   859  }
   860  
   861  func TestLabelService_GetLabel(t *testing.T) {
   862  	// GIVEN
   863  	tnt := tenantID
   864  	externalTnt := "external-tenant"
   865  	id := "foo"
   866  	ctx := context.TODO()
   867  	ctx = tenant.SaveToContext(ctx, tnt, externalTnt)
   868  	version := 0
   869  
   870  	testErr := errors.New("Test error")
   871  
   872  	testCases := []struct {
   873  		Name           string
   874  		LabelRepoFn    func() *automock.LabelRepository
   875  		LabelDefRepoFn func() *automock.LabelDefinitionRepository
   876  		UIDServiceFn   func() *automock.UIDService
   877  
   878  		LabelInput *model.LabelInput
   879  
   880  		ExpectedLabel      *model.Label
   881  		ExpectedErrMessage string
   882  	}{
   883  		{
   884  			Name: "Success",
   885  			LabelInput: &model.LabelInput{
   886  				Key:        "test",
   887  				Value:      []interface{}{"test"},
   888  				ObjectType: model.ApplicationLabelableObject,
   889  				ObjectID:   "appID",
   890  				Version:    version,
   891  			},
   892  			LabelRepoFn: func() *automock.LabelRepository {
   893  				repo := &automock.LabelRepository{}
   894  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, "appID", "test").Return(&model.Label{
   895  					ID:         id,
   896  					Key:        "test",
   897  					Value:      []interface{}{"test"},
   898  					ObjectID:   "appID",
   899  					ObjectType: model.ApplicationLabelableObject,
   900  					Version:    version,
   901  				}, nil)
   902  				return repo
   903  			},
   904  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   905  				repo := &automock.LabelDefinitionRepository{}
   906  				return repo
   907  			},
   908  			UIDServiceFn: func() *automock.UIDService {
   909  				svc := &automock.UIDService{}
   910  				return svc
   911  			},
   912  
   913  			ExpectedLabel: &model.Label{
   914  				ID:         id,
   915  				Key:        "test",
   916  				Value:      []interface{}{"test"},
   917  				ObjectID:   "appID",
   918  				ObjectType: model.ApplicationLabelableObject,
   919  				Version:    version,
   920  			},
   921  			ExpectedErrMessage: "",
   922  		},
   923  		{
   924  			Name: "Error while getting Label",
   925  			LabelInput: &model.LabelInput{
   926  				Key:        "test",
   927  				Value:      []interface{}{"test"},
   928  				ObjectType: model.ApplicationLabelableObject,
   929  				ObjectID:   "appID",
   930  				Version:    version,
   931  			},
   932  			LabelRepoFn: func() *automock.LabelRepository {
   933  				repo := &automock.LabelRepository{}
   934  				repo.On("GetByKey", ctx, tnt, model.ApplicationLabelableObject, "appID", "test").Return(nil, testErr)
   935  				return repo
   936  			},
   937  			LabelDefRepoFn: func() *automock.LabelDefinitionRepository {
   938  				repo := &automock.LabelDefinitionRepository{}
   939  				return repo
   940  			},
   941  			UIDServiceFn: func() *automock.UIDService {
   942  				svc := &automock.UIDService{}
   943  				return svc
   944  			},
   945  
   946  			ExpectedLabel:      nil,
   947  			ExpectedErrMessage: "Test error",
   948  		},
   949  	}
   950  
   951  	for _, testCase := range testCases {
   952  		t.Run(testCase.Name, func(t *testing.T) {
   953  			labelRepo := testCase.LabelRepoFn()
   954  			labelDefRepo := testCase.LabelDefRepoFn()
   955  			uidService := testCase.UIDServiceFn()
   956  
   957  			svc := label.NewLabelService(labelRepo, labelDefRepo, uidService)
   958  
   959  			// WHEN
   960  			lbl, err := svc.GetLabel(ctx, tnt, testCase.LabelInput)
   961  
   962  			// then
   963  			if testCase.ExpectedErrMessage == "" {
   964  				require.NoError(t, err)
   965  				assert.Equal(t, testCase.ExpectedLabel, lbl)
   966  			} else {
   967  				require.Error(t, err)
   968  				require.Nil(t, lbl)
   969  				assert.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   970  			}
   971  
   972  			labelRepo.AssertExpectations(t)
   973  			labelDefRepo.AssertExpectations(t)
   974  			uidService.AssertExpectations(t)
   975  		})
   976  	}
   977  }