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

     1  package labeldef_test
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"errors"
     7  	"reflect"
     8  	"regexp"
     9  	"testing"
    10  
    11  	"github.com/kyma-incubator/compass/components/director/internal/repo/testdb"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/mock"
    15  
    16  	"github.com/DATA-DOG/go-sqlmock"
    17  	"github.com/kyma-incubator/compass/components/director/internal/domain/labeldef"
    18  	"github.com/kyma-incubator/compass/components/director/internal/domain/labeldef/automock"
    19  	"github.com/kyma-incubator/compass/components/director/internal/model"
    20  	"github.com/kyma-incubator/compass/components/director/pkg/persistence"
    21  	"github.com/stretchr/testify/require"
    22  )
    23  
    24  func TestRepositoryCreateLabelDefinition(t *testing.T) {
    25  	// GIVEN
    26  	labelDefID := "d048f47b-b700-49ed-913d-180c3748164b"
    27  	tenantID := "003a0855-4eb0-486d-8fc6-3ab2f2312ca0"
    28  	someString := "any"
    29  	version := 42
    30  	var someSchema interface{} = someString
    31  
    32  	in := model.LabelDefinition{
    33  		ID:      labelDefID,
    34  		Tenant:  tenantID,
    35  		Key:     "some-key",
    36  		Schema:  &someSchema,
    37  		Version: version,
    38  	}
    39  
    40  	t.Run("successfully created definition with schema", func(t *testing.T) {
    41  		db, dbMock := testdb.MockDatabase(t)
    42  		ctx := context.TODO()
    43  		ctx = persistence.SaveToContext(ctx, db)
    44  		mockConverter := &automock.EntityConverter{}
    45  		defer mockConverter.AssertExpectations(t)
    46  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{String: "any", Valid: true}, Version: version}, nil)
    47  		escapedQuery := regexp.QuoteMeta("INSERT INTO public.label_definitions ( id, tenant_id, key, schema, version ) VALUES ( ?, ?, ?, ?, ? )")
    48  		dbMock.ExpectExec(escapedQuery).WithArgs(labelDefID, tenantID, "some-key", "any", version).WillReturnResult(sqlmock.NewResult(1, 1))
    49  
    50  		defer dbMock.AssertExpectations(t)
    51  		sut := labeldef.NewRepository(mockConverter)
    52  		// WHEN
    53  		err := sut.Create(ctx, in)
    54  		// THEN
    55  		require.NoError(t, err)
    56  	})
    57  
    58  	t.Run("successfully created definition without schema", func(t *testing.T) {
    59  		db, dbMock := testdb.MockDatabase(t)
    60  		ctx := context.TODO()
    61  		ctx = persistence.SaveToContext(ctx, db)
    62  		mockConverter := &automock.EntityConverter{}
    63  		defer mockConverter.AssertExpectations(t)
    64  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{}, Version: version}, nil)
    65  		escapedQuery := regexp.QuoteMeta("INSERT INTO public.label_definitions ( id, tenant_id, key, schema, version ) VALUES ( ?, ?, ?, ?, ? )")
    66  		dbMock.ExpectExec(escapedQuery).WithArgs(labelDefID, tenantID, "some-key", nil, version).WillReturnResult(sqlmock.NewResult(1, 1))
    67  		defer dbMock.AssertExpectations(t)
    68  		sut := labeldef.NewRepository(mockConverter)
    69  		// WHEN
    70  		err := sut.Create(ctx, in)
    71  		// THEN
    72  		require.NoError(t, err)
    73  	})
    74  
    75  	t.Run("returns error if insert fails", func(t *testing.T) {
    76  		mockConverter := &automock.EntityConverter{}
    77  		defer mockConverter.AssertExpectations(t)
    78  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{String: "any", Valid: true}, Version: version}, nil)
    79  
    80  		sut := labeldef.NewRepository(mockConverter)
    81  		db, dbMock := testdb.MockDatabase(t)
    82  		ctx := context.TODO()
    83  		ctx = persistence.SaveToContext(ctx, db)
    84  		escapedQuery := regexp.QuoteMeta("INSERT INTO public.label_definitions ( id, tenant_id, key, schema, version ) VALUES ( ?, ?, ?, ?, ? )")
    85  		dbMock.ExpectExec(escapedQuery).WillReturnError(errors.New("some error"))
    86  		defer dbMock.AssertExpectations(t)
    87  		// WHEN
    88  		err := sut.Create(ctx, in)
    89  		// THEN
    90  		require.EqualError(t, err, "while inserting Label Definition: Internal Server Error: Unexpected error while executing SQL query")
    91  	})
    92  }
    93  
    94  func TestRepositoryUpdateLabelDefinition(t *testing.T) {
    95  	// GIVEN
    96  	labelDefID := "d048f47b-b700-49ed-913d-180c3748164b"
    97  	tenantID := "003a0855-4eb0-486d-8fc6-3ab2f2312ca0"
    98  	someString := "any"
    99  	version := 42
   100  	var someSchema interface{} = someString
   101  
   102  	in := model.LabelDefinition{
   103  		ID:     labelDefID,
   104  		Tenant: tenantID,
   105  		Key:    "some-key",
   106  		Schema: &someSchema,
   107  	}
   108  
   109  	t.Run("successfully updated definition with schema", func(t *testing.T) {
   110  		db, dbMock := testdb.MockDatabase(t)
   111  
   112  		ctx := context.TODO()
   113  		ctx = persistence.SaveToContext(ctx, db)
   114  
   115  		mockConverter := &automock.EntityConverter{}
   116  		defer mockConverter.AssertExpectations(t)
   117  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{String: "any", Valid: true}, Version: version}, nil)
   118  
   119  		escapedQuery := regexp.QuoteMeta(`UPDATE public.label_definitions SET schema = ?, version = version+1 WHERE id = ? AND tenant_id = ?`)
   120  		dbMock.ExpectExec(escapedQuery).WithArgs("any", labelDefID, tenantID).WillReturnResult(sqlmock.NewResult(1, 1))
   121  		defer dbMock.AssertExpectations(t)
   122  
   123  		sut := labeldef.NewRepository(mockConverter)
   124  
   125  		// WHEN
   126  		err := sut.Update(ctx, in)
   127  		// THEN
   128  		require.NoError(t, err)
   129  	})
   130  
   131  	t.Run("successfully updated definition without schema", func(t *testing.T) {
   132  		db, dbMock := testdb.MockDatabase(t)
   133  
   134  		ctx := context.TODO()
   135  		ctx = persistence.SaveToContext(ctx, db)
   136  
   137  		mockConverter := &automock.EntityConverter{}
   138  		defer mockConverter.AssertExpectations(t)
   139  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, Version: version}, nil)
   140  
   141  		escapedQuery := regexp.QuoteMeta(`UPDATE public.label_definitions SET schema = ?, version = version+1 WHERE id = ? AND tenant_id = ?`)
   142  		dbMock.ExpectExec(escapedQuery).WithArgs(nil, labelDefID, tenantID).WillReturnResult(sqlmock.NewResult(1, 1))
   143  		defer dbMock.AssertExpectations(t)
   144  
   145  		sut := labeldef.NewRepository(mockConverter)
   146  
   147  		// WHEN
   148  		err := sut.Update(ctx, in)
   149  		// THEN
   150  		require.NoError(t, err)
   151  	})
   152  
   153  	t.Run("returns error if update fails", func(t *testing.T) {
   154  		mockConverter := &automock.EntityConverter{}
   155  		defer mockConverter.AssertExpectations(t)
   156  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{String: "any", Valid: true}, Version: version}, nil)
   157  
   158  		sut := labeldef.NewRepository(mockConverter)
   159  		db, dbMock := testdb.MockDatabase(t)
   160  
   161  		ctx := context.TODO()
   162  		ctx = persistence.SaveToContext(ctx, db)
   163  
   164  		escapedQuery := regexp.QuoteMeta(`UPDATE public.label_definitions SET schema = ?, version = version+1 WHERE id = ? AND tenant_id = ?`)
   165  		dbMock.ExpectExec(escapedQuery).WillReturnError(errors.New("some error"))
   166  		defer dbMock.AssertExpectations(t)
   167  
   168  		// WHEN
   169  		err := sut.Update(ctx, in)
   170  		// THEN
   171  		require.EqualError(t, err, "Internal Server Error: Unexpected error while executing SQL query")
   172  	})
   173  
   174  	t.Run("returns error if update fails", func(t *testing.T) {
   175  		mockConverter := &automock.EntityConverter{}
   176  		defer mockConverter.AssertExpectations(t)
   177  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{String: "any", Valid: true}, Version: version}, nil)
   178  
   179  		sut := labeldef.NewRepository(mockConverter)
   180  		db, dbMock := testdb.MockDatabase(t)
   181  
   182  		ctx := context.TODO()
   183  		ctx = persistence.SaveToContext(ctx, db)
   184  
   185  		escapedQuery := regexp.QuoteMeta(`UPDATE public.label_definitions SET schema = ?, version = version+1 WHERE id = ? AND tenant_id = ?`)
   186  		dbMock.ExpectExec(escapedQuery).WillReturnError(errors.New("some error"))
   187  		defer dbMock.AssertExpectations(t)
   188  
   189  		// WHEN
   190  		err := sut.Update(ctx, in)
   191  		// THEN
   192  		require.EqualError(t, err, "Internal Server Error: Unexpected error while executing SQL query")
   193  	})
   194  
   195  	t.Run("returns error if no row was affected by query", func(t *testing.T) {
   196  		db, dbMock := testdb.MockDatabase(t)
   197  
   198  		ctx := context.TODO()
   199  		ctx = persistence.SaveToContext(ctx, db)
   200  
   201  		mockConverter := &automock.EntityConverter{}
   202  		defer mockConverter.AssertExpectations(t)
   203  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{String: "any", Valid: true}, Version: version}, nil)
   204  
   205  		escapedQuery := regexp.QuoteMeta(`UPDATE public.label_definitions SET schema = ?, version = version+1 WHERE id = ? AND tenant_id = ?`)
   206  		dbMock.ExpectExec(escapedQuery).WithArgs("any", labelDefID, tenantID).WillReturnResult(sqlmock.NewResult(1, 0))
   207  		defer dbMock.AssertExpectations(t)
   208  
   209  		sut := labeldef.NewRepository(mockConverter)
   210  
   211  		// WHEN
   212  		err := sut.Update(ctx, in)
   213  		// THEN
   214  		require.EqualError(t, err, "Could not update object due to concurrent update")
   215  	})
   216  }
   217  
   218  func TestRepositoryUpdateLabelDefinitionWithVersion(t *testing.T) {
   219  	// GIVEN
   220  	labelDefID := "d048f47b-b700-49ed-913d-180c3748164b"
   221  	tenantID := "003a0855-4eb0-486d-8fc6-3ab2f2312ca0"
   222  	someString := "any"
   223  	version := 42
   224  	var someSchema interface{} = someString
   225  
   226  	in := model.LabelDefinition{
   227  		ID:     labelDefID,
   228  		Tenant: tenantID,
   229  		Key:    "some-key",
   230  		Schema: &someSchema,
   231  	}
   232  
   233  	t.Run("successfully updated definition with schema", func(t *testing.T) {
   234  		db, dbMock := testdb.MockDatabase(t)
   235  
   236  		ctx := context.TODO()
   237  		ctx = persistence.SaveToContext(ctx, db)
   238  
   239  		mockConverter := &automock.EntityConverter{}
   240  		defer mockConverter.AssertExpectations(t)
   241  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{String: "any", Valid: true}, Version: version}, nil)
   242  
   243  		escapedQuery := regexp.QuoteMeta(`UPDATE public.label_definitions SET schema = ?, version = version+1 WHERE id = ? AND version = ? AND tenant_id = ?`)
   244  		dbMock.ExpectExec(escapedQuery).WithArgs("any", labelDefID, version, tenantID).WillReturnResult(sqlmock.NewResult(1, 1))
   245  		defer dbMock.AssertExpectations(t)
   246  
   247  		sut := labeldef.NewRepository(mockConverter)
   248  
   249  		// WHEN
   250  		err := sut.UpdateWithVersion(ctx, in)
   251  		// THEN
   252  		require.NoError(t, err)
   253  	})
   254  
   255  	t.Run("successfully updated definition without schema", func(t *testing.T) {
   256  		db, dbMock := testdb.MockDatabase(t)
   257  
   258  		ctx := context.TODO()
   259  		ctx = persistence.SaveToContext(ctx, db)
   260  
   261  		mockConverter := &automock.EntityConverter{}
   262  		defer mockConverter.AssertExpectations(t)
   263  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, Version: version}, nil)
   264  
   265  		escapedQuery := regexp.QuoteMeta(`UPDATE public.label_definitions SET schema = ?, version = version+1 WHERE id = ? AND version = ? AND tenant_id = ?`)
   266  		dbMock.ExpectExec(escapedQuery).WithArgs(nil, labelDefID, version, tenantID).WillReturnResult(sqlmock.NewResult(1, 1))
   267  		defer dbMock.AssertExpectations(t)
   268  
   269  		sut := labeldef.NewRepository(mockConverter)
   270  
   271  		// WHEN
   272  		err := sut.UpdateWithVersion(ctx, in)
   273  		// THEN
   274  		require.NoError(t, err)
   275  	})
   276  
   277  	t.Run("returns error if update fails", func(t *testing.T) {
   278  		mockConverter := &automock.EntityConverter{}
   279  		defer mockConverter.AssertExpectations(t)
   280  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{String: "any", Valid: true}, Version: version}, nil)
   281  
   282  		sut := labeldef.NewRepository(mockConverter)
   283  		db, dbMock := testdb.MockDatabase(t)
   284  
   285  		ctx := context.TODO()
   286  		ctx = persistence.SaveToContext(ctx, db)
   287  
   288  		escapedQuery := regexp.QuoteMeta(`UPDATE public.label_definitions SET schema = ?, version = version+1 WHERE id = ? AND version = ? AND tenant_id = ?`)
   289  		dbMock.ExpectExec(escapedQuery).WillReturnError(errors.New("some error"))
   290  		defer dbMock.AssertExpectations(t)
   291  
   292  		// WHEN
   293  		err := sut.UpdateWithVersion(ctx, in)
   294  		// THEN
   295  		require.EqualError(t, err, "Internal Server Error: Unexpected error while executing SQL query")
   296  	})
   297  
   298  	t.Run("returns error if no row was affected by query", func(t *testing.T) {
   299  		db, dbMock := testdb.MockDatabase(t)
   300  
   301  		ctx := context.TODO()
   302  		ctx = persistence.SaveToContext(ctx, db)
   303  
   304  		mockConverter := &automock.EntityConverter{}
   305  		defer mockConverter.AssertExpectations(t)
   306  		mockConverter.On("ToEntity", in).Return(labeldef.Entity{ID: labelDefID, Key: "some-key", TenantID: tenantID, SchemaJSON: sql.NullString{String: "any", Valid: true}, Version: version}, nil)
   307  
   308  		escapedQuery := regexp.QuoteMeta(`UPDATE public.label_definitions SET schema = ?, version = version+1 WHERE id = ? AND version = ? AND tenant_id = ?`)
   309  		dbMock.ExpectExec(escapedQuery).WithArgs("any", labelDefID, version, tenantID).WillReturnResult(sqlmock.NewResult(1, 0))
   310  		defer dbMock.AssertExpectations(t)
   311  
   312  		sut := labeldef.NewRepository(mockConverter)
   313  
   314  		// WHEN
   315  		err := sut.UpdateWithVersion(ctx, in)
   316  		// THEN
   317  		require.EqualError(t, err, "Could not update object due to concurrent update")
   318  	})
   319  }
   320  
   321  func TestRepositoryGetByKey(t *testing.T) {
   322  	t.Run("returns LabelDefinition", func(t *testing.T) {
   323  		// GIVEN
   324  		mockConverter := &automock.EntityConverter{}
   325  		defer mockConverter.AssertExpectations(t)
   326  
   327  		var someSchema interface{} = ExampleSchema{Title: "title"}
   328  		mockConverter.On("FromEntity",
   329  			labeldef.Entity{ID: "id", TenantID: "tenant", Key: "key", SchemaJSON: sql.NullString{Valid: true, String: `{"title":"title"}`}}).
   330  			Return(
   331  				model.LabelDefinition{
   332  					ID:     "id",
   333  					Tenant: "tenant",
   334  					Key:    "key",
   335  					Schema: &someSchema}, nil)
   336  		sut := labeldef.NewRepository(mockConverter)
   337  
   338  		db, dbMock := testdb.MockDatabase(t)
   339  		defer dbMock.AssertExpectations(t)
   340  
   341  		mockedRows := sqlmock.NewRows([]string{"id", "tenant_id", "key", "schema"}).AddRow("id", "tenant", "key", `{"title":"title"}`)
   342  		dbMock.ExpectQuery(`^SELECT (.+) FROM public.label_definitions WHERE tenant_id = \$1 AND key = \$2$`).
   343  			WithArgs("tenant", "key").WillReturnRows(mockedRows)
   344  
   345  		ctx := context.TODO()
   346  		ctx = persistence.SaveToContext(ctx, db)
   347  		// WHEN
   348  		actual, err := sut.GetByKey(ctx, "tenant", "key")
   349  		// THEN
   350  		require.NoError(t, err)
   351  		assert.Equal(t, "id", actual.ID)
   352  		assert.Equal(t, "tenant", actual.Tenant)
   353  		assert.Equal(t, "key", actual.Key)
   354  		assert.Equal(t, &someSchema, actual.Schema)
   355  	})
   356  	t.Run("returns errorNotFound if LabelDefinition does not exist", func(t *testing.T) {
   357  		// GIVEN
   358  		db, dbMock := testdb.MockDatabase(t)
   359  		defer dbMock.AssertExpectations(t)
   360  
   361  		dbMock.ExpectQuery(`^SELECT (.+) FROM public.label_definitions WHERE tenant_id = \$1 AND key = \$2$`).
   362  			WithArgs("anything", "anything").WillReturnRows(sqlmock.NewRows([]string{"id", "tenant_id", "key", "schema"}))
   363  		ctx := context.TODO()
   364  		ctx = persistence.SaveToContext(ctx, db)
   365  
   366  		sut := labeldef.NewRepository(nil)
   367  		// WHEN
   368  		actual, err := sut.GetByKey(ctx, "anything", "anything")
   369  		// THEN
   370  		require.Error(t, err)
   371  		assert.Contains(t, err.Error(), "Object not found")
   372  		assert.Nil(t, actual)
   373  	})
   374  	t.Run("returns error when conversion fails", func(t *testing.T) {
   375  		// GIVEN
   376  		mockConverter := &automock.EntityConverter{}
   377  		defer mockConverter.AssertExpectations(t)
   378  		mockConverter.On("FromEntity", mock.Anything).Return(model.LabelDefinition{}, errors.New("conversion error"))
   379  		sut := labeldef.NewRepository(mockConverter)
   380  
   381  		db, dbMock := testdb.MockDatabase(t)
   382  		defer dbMock.AssertExpectations(t)
   383  
   384  		mockedRows := sqlmock.NewRows([]string{"id", "tenant_id", "key", "schema"}).AddRow("id", "tenant", "key", `{"title":"title"}`)
   385  		dbMock.ExpectQuery(`^SELECT (.+) FROM public.label_definitions WHERE tenant_id = \$1 AND key = \$2$`).
   386  			WithArgs("tenant", "key").WillReturnRows(mockedRows)
   387  
   388  		ctx := context.TODO()
   389  		ctx = persistence.SaveToContext(ctx, db)
   390  		// WHEN
   391  		_, err := sut.GetByKey(ctx, "tenant", "key")
   392  		// THEN
   393  		require.EqualError(t, err, "while converting Label Definition: conversion error")
   394  	})
   395  	t.Run("returns error if select fails", func(t *testing.T) {
   396  		// GIVEN
   397  		sut := labeldef.NewRepository(nil)
   398  		db, dbMock := testdb.MockDatabase(t)
   399  		defer dbMock.AssertExpectations(t)
   400  
   401  		dbMock.ExpectQuery(`^SELECT (.+) FROM public.label_definitions WHERE tenant_id = \$1 AND key = \$2$`).
   402  			WithArgs("tenant", "key").WillReturnError(errors.New("persistence error"))
   403  
   404  		ctx := context.TODO()
   405  		ctx = persistence.SaveToContext(ctx, db)
   406  		// WHEN
   407  		_, err := sut.GetByKey(ctx, "tenant", "key")
   408  		// THEN
   409  		require.EqualError(t, err, "while getting Label Definition by key=key: Internal Server Error: Unexpected error while executing SQL query")
   410  	})
   411  }
   412  
   413  func TestRepositoryList(t *testing.T) {
   414  	t.Run("returns list of Label Definitions", func(t *testing.T) {
   415  		// GIVEN
   416  		mockConverter := &automock.EntityConverter{}
   417  		defer mockConverter.AssertExpectations(t)
   418  
   419  		mockConverter.On("FromEntity",
   420  			labeldef.Entity{ID: "id1", TenantID: "tenant", Key: "key1", Version: 0}).
   421  			Return(
   422  				model.LabelDefinition{
   423  					ID:      "id1",
   424  					Tenant:  "tenant",
   425  					Key:     "key1",
   426  					Version: 0,
   427  				}, nil)
   428  		mockConverter.On("FromEntity",
   429  			labeldef.Entity{ID: "id2", TenantID: "tenant", Key: "key2", SchemaJSON: sql.NullString{Valid: true, String: `{"title":"title"}`}, Version: 0}).
   430  			Return(
   431  				model.LabelDefinition{
   432  					ID:      "id2",
   433  					Tenant:  "tenant",
   434  					Key:     "key2",
   435  					Version: 0,
   436  				}, nil)
   437  		sut := labeldef.NewRepository(mockConverter)
   438  
   439  		db, dbMock := testdb.MockDatabase(t)
   440  		defer dbMock.AssertExpectations(t)
   441  
   442  		mockedRows := sqlmock.NewRows([]string{"id", "tenant_id", "key", "schema", "version"}).
   443  			AddRow("id1", "tenant", "key1", nil, 0).
   444  			AddRow("id2", "tenant", "key2", `{"title":"title"}`, 0)
   445  
   446  		dbMock.ExpectQuery(`^SELECT (.+) FROM public.label_definitions WHERE tenant_id = \$1$`).WithArgs("tenant").WillReturnRows(mockedRows)
   447  
   448  		ctx := context.TODO()
   449  		ctx = persistence.SaveToContext(ctx, db)
   450  		// WHEN
   451  		actual, err := sut.List(ctx, "tenant")
   452  		// THEN
   453  		require.NoError(t, err)
   454  		require.Len(t, actual, 2)
   455  		assert.Equal(t, "id1", actual[0].ID)
   456  		assert.Equal(t, "key1", actual[0].Key)
   457  		assert.Equal(t, 0, actual[0].Version)
   458  		assert.Equal(t, "id2", actual[1].ID)
   459  		assert.Equal(t, "key2", actual[1].Key)
   460  		assert.Equal(t, 0, actual[1].Version)
   461  	})
   462  	t.Run("returns empty list of Label Definitions if given tenant has nothing defined", func(t *testing.T) {
   463  		// GIVEN
   464  		sut := labeldef.NewRepository(nil)
   465  
   466  		db, dbMock := testdb.MockDatabase(t)
   467  		defer dbMock.AssertExpectations(t)
   468  
   469  		mockedRows := sqlmock.NewRows([]string{"id", "tenant_id", "key", "schema", "version"})
   470  
   471  		dbMock.ExpectQuery(`^SELECT (.+) FROM public.label_definitions WHERE tenant_id = \$1$`).WithArgs("tenant").WillReturnRows(mockedRows)
   472  
   473  		ctx := context.TODO()
   474  		ctx = persistence.SaveToContext(ctx, db)
   475  		// WHEN
   476  		actual, err := sut.List(ctx, "tenant")
   477  		// THEN
   478  		require.NoError(t, err)
   479  		require.Empty(t, actual)
   480  	})
   481  
   482  	t.Run("returns error when conversion fails", func(t *testing.T) {
   483  		// GIVEN
   484  		mockConverter := &automock.EntityConverter{}
   485  		defer mockConverter.AssertExpectations(t)
   486  
   487  		mockConverter.On("FromEntity",
   488  			labeldef.Entity{ID: "id1", TenantID: "tenant", Key: "key1", Version: 0}).
   489  			Return(
   490  				model.LabelDefinition{}, errors.New("conversion error"))
   491  
   492  		sut := labeldef.NewRepository(mockConverter)
   493  
   494  		db, dbMock := testdb.MockDatabase(t)
   495  		defer dbMock.AssertExpectations(t)
   496  
   497  		mockedRows := sqlmock.NewRows([]string{"id", "tenant_id", "key", "schema", "version"}).
   498  			AddRow("id1", "tenant", "key1", nil, 0).
   499  			AddRow("id2", "tenant", "key2", `{"title":"title"}`, 0)
   500  
   501  		dbMock.ExpectQuery(`^SELECT (.+) FROM public.label_definitions WHERE tenant_id = \$1$`).WithArgs("tenant").WillReturnRows(mockedRows)
   502  
   503  		ctx := context.TODO()
   504  		ctx = persistence.SaveToContext(ctx, db)
   505  		// WHEN
   506  		_, err := sut.List(ctx, "tenant")
   507  		// THEN
   508  		require.EqualError(t, err, "while converting Label Definition [key=key1]: conversion error")
   509  	})
   510  	t.Run("returns error if if select fails", func(t *testing.T) {
   511  		// GIVEN
   512  		sut := labeldef.NewRepository(nil)
   513  
   514  		db, dbMock := testdb.MockDatabase(t)
   515  		defer dbMock.AssertExpectations(t)
   516  
   517  		dbMock.ExpectQuery(`^SELECT (.+) FROM public.label_definitions WHERE tenant_id = \$1$`).
   518  			WithArgs("tenant").WillReturnError(errors.New("db error"))
   519  
   520  		ctx := context.TODO()
   521  		ctx = persistence.SaveToContext(ctx, db)
   522  		// WHEN
   523  		_, err := sut.List(ctx, "tenant")
   524  		// THEN
   525  		require.EqualError(t, err, "while listing Label Definitions: Internal Server Error: Unexpected error while executing SQL query")
   526  	})
   527  }
   528  
   529  func TestRepositoryLabelDefExists(t *testing.T) {
   530  	t.Run("returns true", func(t *testing.T) {
   531  		// GIVEN
   532  		sut := labeldef.NewRepository(nil)
   533  		db, dbMock := testdb.MockDatabase(t)
   534  		defer dbMock.AssertExpectations(t)
   535  
   536  		escapedQuery := regexp.QuoteMeta("SELECT 1 FROM public.label_definitions WHERE tenant_id = $1 AND key = $2")
   537  		dbMock.ExpectQuery(escapedQuery).WithArgs("tenant", "key").WillReturnRows(sqlmock.NewRows([]string{"exists"}).AddRow("1"))
   538  
   539  		ctx := context.TODO()
   540  		ctx = persistence.SaveToContext(ctx, db)
   541  		// WHEN
   542  		actual, err := sut.Exists(ctx, "tenant", "key")
   543  		// THEN
   544  		require.NoError(t, err)
   545  		assert.True(t, actual)
   546  	})
   547  
   548  	t.Run("returns false", func(t *testing.T) {
   549  		// GIVEN
   550  		db, dbMock := testdb.MockDatabase(t)
   551  		defer dbMock.AssertExpectations(t)
   552  
   553  		escapedQuery := regexp.QuoteMeta("SELECT 1 FROM public.label_definitions WHERE tenant_id = $1 AND key = $2")
   554  		dbMock.ExpectQuery(escapedQuery).WithArgs("anything", "anything").WillReturnRows(sqlmock.NewRows([]string{"exists"}))
   555  		ctx := context.TODO()
   556  		ctx = persistence.SaveToContext(ctx, db)
   557  
   558  		sut := labeldef.NewRepository(nil)
   559  		// WHEN
   560  		actual, err := sut.Exists(ctx, "anything", "anything")
   561  		// THEN
   562  		require.NoError(t, err)
   563  		assert.False(t, actual)
   564  	})
   565  	t.Run("returns error if select fails", func(t *testing.T) {
   566  		// GIVEN
   567  		sut := labeldef.NewRepository(nil)
   568  		db, dbMock := testdb.MockDatabase(t)
   569  		defer dbMock.AssertExpectations(t)
   570  
   571  		escapedQuery := regexp.QuoteMeta("SELECT 1 FROM public.label_definitions WHERE tenant_id = $1 AND key = $2")
   572  		dbMock.ExpectQuery(escapedQuery).WithArgs("tenant", "key").WillReturnError(errors.New("persistence error"))
   573  
   574  		ctx := context.TODO()
   575  		ctx = persistence.SaveToContext(ctx, db)
   576  		// WHEN
   577  		_, err := sut.Exists(ctx, "tenant", "key")
   578  		// THEN
   579  		require.EqualError(t, err, "Internal Server Error: Unexpected error while executing SQL query")
   580  	})
   581  }
   582  
   583  func TestRepository_DeleteByKey(t *testing.T) {
   584  	t.Run("Success", func(t *testing.T) {
   585  		// GIVEN
   586  		key := "test"
   587  		tnt := "tenant"
   588  
   589  		mockConverter := &automock.EntityConverter{}
   590  		defer mockConverter.AssertExpectations(t)
   591  
   592  		repo := labeldef.NewRepository(mockConverter)
   593  
   594  		db, dbMock := testdb.MockDatabase(t)
   595  		defer dbMock.AssertExpectations(t)
   596  
   597  		escapedQuery := regexp.QuoteMeta("DELETE FROM public.label_definitions WHERE tenant_id = $1 AND key = $2")
   598  		dbMock.ExpectExec(escapedQuery).WithArgs(tnt, key).WillReturnResult(sqlmock.NewResult(1, 1))
   599  
   600  		ctx := context.TODO()
   601  		ctx = persistence.SaveToContext(ctx, db)
   602  		// WHEN
   603  		err := repo.DeleteByKey(ctx, tnt, key)
   604  		// THEN
   605  		require.NoError(t, err)
   606  	})
   607  
   608  	t.Run("Error - Operation", func(t *testing.T) {
   609  		// GIVEN
   610  		key := "test"
   611  		tnt := "tenant"
   612  		testErr := errors.New("Test err")
   613  
   614  		mockConverter := &automock.EntityConverter{}
   615  		defer mockConverter.AssertExpectations(t)
   616  
   617  		repo := labeldef.NewRepository(mockConverter)
   618  
   619  		db, dbMock := testdb.MockDatabase(t)
   620  		defer dbMock.AssertExpectations(t)
   621  
   622  		escapedQuery := regexp.QuoteMeta("DELETE FROM public.label_definitions WHERE tenant_id = $1 AND key = $2")
   623  		dbMock.ExpectExec(escapedQuery).WithArgs(tnt, key).WillReturnError(testErr)
   624  
   625  		ctx := context.TODO()
   626  		ctx = persistence.SaveToContext(ctx, db)
   627  		// WHEN
   628  		err := repo.DeleteByKey(ctx, tnt, key)
   629  		// THEN
   630  		require.Error(t, err)
   631  		assert.Contains(t, err.Error(), "Internal Server Error: Unexpected error while executing SQL query")
   632  	})
   633  
   634  	t.Run("Error - No rows affected", func(t *testing.T) {
   635  		// GIVEN
   636  		key := "test"
   637  		tnt := "tenant"
   638  
   639  		mockConverter := &automock.EntityConverter{}
   640  		defer mockConverter.AssertExpectations(t)
   641  
   642  		repo := labeldef.NewRepository(mockConverter)
   643  
   644  		db, dbMock := testdb.MockDatabase(t)
   645  		defer dbMock.AssertExpectations(t)
   646  
   647  		escapedQuery := regexp.QuoteMeta("DELETE FROM public.label_definitions WHERE tenant_id = $1 AND key = $2")
   648  		dbMock.ExpectExec(escapedQuery).WithArgs(tnt, key).WillReturnResult(sqlmock.NewResult(1, 0))
   649  
   650  		ctx := context.TODO()
   651  		ctx = persistence.SaveToContext(ctx, db)
   652  		// WHEN
   653  		err := repo.DeleteByKey(ctx, tnt, key)
   654  		// THEN
   655  		require.EqualError(t, err, "Unauthorized [reason=Owner access is needed for resource modification]")
   656  	})
   657  }
   658  
   659  func TestRepository_Upsert(t *testing.T) {
   660  	t.Run("Success - Label for Runtime", func(t *testing.T) {
   661  		// GIVEN
   662  		key := "test"
   663  		tnt := "tenant"
   664  		schema := "{}"
   665  		schemaInterface := reflect.ValueOf(schema).Interface()
   666  		version := 42
   667  
   668  		labeldefModel := model.LabelDefinition{
   669  			ID:      "foo",
   670  			Tenant:  tnt,
   671  			Key:     key,
   672  			Schema:  &schemaInterface,
   673  			Version: version,
   674  		}
   675  		labeldefEntity := labeldef.Entity{
   676  			ID:       "foo",
   677  			TenantID: tnt,
   678  			Key:      key,
   679  			SchemaJSON: sql.NullString{
   680  				String: schema,
   681  				Valid:  true,
   682  			},
   683  			Version: version,
   684  		}
   685  
   686  		mockConverter := &automock.EntityConverter{}
   687  		mockConverter.On("ToEntity", labeldefModel).Return(labeldefEntity, nil).Once()
   688  		defer mockConverter.AssertExpectations(t)
   689  
   690  		labelRepo := labeldef.NewRepository(mockConverter)
   691  
   692  		db, dbMock := testdb.MockDatabase(t)
   693  		defer dbMock.AssertExpectations(t)
   694  
   695  		escapedQuery := regexp.QuoteMeta(`INSERT INTO public.label_definitions ( id, tenant_id, key, schema, version ) VALUES ( ?, ?, ?, ?, ? ) ON CONFLICT ( tenant_id, key ) DO UPDATE SET schema=EXCLUDED.schema WHERE  public.label_definitions.tenant_id = ?`)
   696  		dbMock.ExpectExec(escapedQuery).WithArgs(labeldefEntity.ID, labeldefEntity.TenantID, labeldefEntity.Key, labeldefEntity.SchemaJSON, labeldefEntity.Version, labeldefEntity.TenantID).WillReturnResult(sqlmock.NewResult(1, 1))
   697  
   698  		ctx := context.TODO()
   699  		ctx = persistence.SaveToContext(ctx, db)
   700  		// WHEN
   701  		err := labelRepo.Upsert(ctx, labeldefModel)
   702  		// THEN
   703  		require.NoError(t, err)
   704  	})
   705  
   706  	t.Run("Error when entityConverting fails", func(t *testing.T) {
   707  		labeldefModel := model.LabelDefinition{}
   708  		labeldefEntity := labeldef.Entity{}
   709  		testErr := errors.New("test-err")
   710  
   711  		mockConverter := &automock.EntityConverter{}
   712  		mockConverter.On("ToEntity", labeldefModel).Return(labeldefEntity, testErr).Once()
   713  		defer mockConverter.AssertExpectations(t)
   714  
   715  		labelRepo := labeldef.NewRepository(mockConverter)
   716  
   717  		// WHEN
   718  		ctx := context.TODO()
   719  		err := labelRepo.Upsert(ctx, labeldefModel)
   720  		// THEN
   721  		require.Error(t, err)
   722  		require.Contains(t, err.Error(), testErr.Error())
   723  	})
   724  }