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

     1  package bundlereferences_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  
     7  	"github.com/kyma-incubator/compass/components/director/pkg/scope"
     8  
     9  	"regexp"
    10  	"testing"
    11  
    12  	"github.com/DATA-DOG/go-sqlmock"
    13  	"github.com/kyma-incubator/compass/components/director/internal/domain/bundlereferences"
    14  	"github.com/kyma-incubator/compass/components/director/internal/domain/bundlereferences/automock"
    15  	"github.com/kyma-incubator/compass/components/director/internal/model"
    16  	"github.com/kyma-incubator/compass/components/director/internal/repo/testdb"
    17  	"github.com/kyma-incubator/compass/components/director/pkg/persistence"
    18  	"github.com/kyma-incubator/compass/components/director/pkg/str"
    19  	"github.com/stretchr/testify/assert"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  func TestPgRepository_GetByID(t *testing.T) {
    24  	// GIVEN
    25  	apiBundleReferenceEntity := fixAPIBundleReferenceEntity()
    26  
    27  	selectQueryForAPIWithoutBundleID := `SELECT (.+) FROM public\.bundle_references WHERE api_def_id = \$1`
    28  	selectQueryForAPIWithBundleID := `SELECT (.+) FROM public\.bundle_references WHERE api_def_id = \$1 AND bundle_id = \$2`
    29  
    30  	t.Run("success when no bundleID", func(t *testing.T) {
    31  		sqlxDB, sqlMock := testdb.MockDatabase(t)
    32  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
    33  			AddRow(fixBundleReferenceRowWithoutEventID()...)
    34  
    35  		sqlMock.ExpectQuery(selectQueryForAPIWithoutBundleID).
    36  			WithArgs(apiDefID).
    37  			WillReturnRows(rows)
    38  
    39  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
    40  		convMock := &automock.BundleReferenceConverter{}
    41  		convMock.On("FromEntity", apiBundleReferenceEntity).Return(fixAPIBundleReferenceModel(), nil).Once()
    42  		pgRepository := bundlereferences.NewRepository(convMock)
    43  
    44  		// WHEN
    45  		modelAPIBundleRef, err := pgRepository.GetByID(ctx, model.BundleAPIReference, str.Ptr(apiDefID), nil)
    46  
    47  		// THEN
    48  		require.NoError(t, err)
    49  		assert.Equal(t, apiDefID, *modelAPIBundleRef.ObjectID)
    50  		convMock.AssertExpectations(t)
    51  		sqlMock.AssertExpectations(t)
    52  	})
    53  	t.Run("success with bundleID", func(t *testing.T) {
    54  		sqlxDB, sqlMock := testdb.MockDatabase(t)
    55  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
    56  			AddRow(fixBundleReferenceRowWithoutEventID()...)
    57  
    58  		sqlMock.ExpectQuery(selectQueryForAPIWithBundleID).
    59  			WithArgs(apiDefID, bundleID).
    60  			WillReturnRows(rows)
    61  
    62  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
    63  		convMock := &automock.BundleReferenceConverter{}
    64  		convMock.On("FromEntity", apiBundleReferenceEntity).Return(fixAPIBundleReferenceModel(), nil).Once()
    65  		pgRepository := bundlereferences.NewRepository(convMock)
    66  
    67  		// WHEN
    68  		modelAPIBundleRef, err := pgRepository.GetByID(ctx, model.BundleAPIReference, str.Ptr(apiDefID), str.Ptr(bundleID))
    69  
    70  		// THEN
    71  		require.NoError(t, err)
    72  		assert.Equal(t, apiDefID, *modelAPIBundleRef.ObjectID)
    73  		convMock.AssertExpectations(t)
    74  		sqlMock.AssertExpectations(t)
    75  	})
    76  }
    77  
    78  func TestPgRepository_GetBundleIDsForObject(t *testing.T) {
    79  	selectQuery := `SELECT (.+) FROM public\.bundle_references WHERE api_def_id = \$1`
    80  
    81  	t.Run("success", func(t *testing.T) {
    82  		// GIVEN
    83  		sqlxDB, sqlMock := testdb.MockDatabase(t)
    84  		rows := sqlmock.NewRows([]string{"bundle_id"}).
    85  			AddRow(fixBundleIDs(bundleID)...).
    86  			AddRow(fixBundleIDs(secondBundleID)...)
    87  
    88  		sqlMock.ExpectQuery(selectQuery).
    89  			WithArgs(apiDefID).
    90  			WillReturnRows(rows)
    91  
    92  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
    93  		convMock := &automock.BundleReferenceConverter{}
    94  		pgRepository := bundlereferences.NewRepository(convMock)
    95  
    96  		// WHEN
    97  		bundleIDs, err := pgRepository.GetBundleIDsForObject(ctx, model.BundleAPIReference, str.Ptr(apiDefID))
    98  
    99  		// THEN
   100  		require.NoError(t, err)
   101  		assert.Equal(t, bundleID, bundleIDs[0])
   102  		assert.Equal(t, secondBundleID, bundleIDs[1])
   103  		sqlMock.AssertExpectations(t)
   104  		convMock.AssertExpectations(t)
   105  	})
   106  }
   107  
   108  func TestPgRepository_Create(t *testing.T) {
   109  	// GIVEN
   110  	bundleRefModel := fixAPIBundleReferenceModel()
   111  	bundleRefEntity := fixAPIBundleReferenceEntity()
   112  	insertQuery := `INSERT INTO public\.bundle_references (.+) VALUES (.+)`
   113  
   114  	t.Run("success", func(t *testing.T) {
   115  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   116  
   117  		sqlMock.ExpectExec(insertQuery).
   118  			WithArgs(fixBundleReferenceCreateArgs(&bundleRefModel)...).
   119  			WillReturnResult(sqlmock.NewResult(-1, 1))
   120  
   121  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   122  		convMock := automock.BundleReferenceConverter{}
   123  		convMock.On("ToEntity", bundleRefModel).Return(bundleRefEntity, nil).Once()
   124  		pgRepository := bundlereferences.NewRepository(&convMock)
   125  
   126  		// WHEN
   127  		err := pgRepository.Create(ctx, &bundleRefModel)
   128  		// THEN
   129  		require.NoError(t, err)
   130  		sqlMock.AssertExpectations(t)
   131  		convMock.AssertExpectations(t)
   132  	})
   133  	t.Run("error when item is nil", func(t *testing.T) {
   134  		ctx := context.TODO()
   135  		convMock := automock.BundleReferenceConverter{}
   136  		pgRepository := bundlereferences.NewRepository(&convMock)
   137  
   138  		// WHEN
   139  		err := pgRepository.Create(ctx, nil)
   140  
   141  		// THEN
   142  		require.Error(t, err)
   143  		assert.Contains(t, err.Error(), "item can not be empty")
   144  		convMock.AssertExpectations(t)
   145  	})
   146  }
   147  
   148  func TestPgRepository_Update(t *testing.T) {
   149  	updateQueryWithoutBundleID := regexp.QuoteMeta(`UPDATE public.bundle_references SET api_def_id = ?, event_def_id = ?, api_def_url = ? WHERE api_def_id = ?`)
   150  	updateQueryWithBundleID := regexp.QuoteMeta(`UPDATE public.bundle_references SET api_def_id = ?, event_def_id = ?, bundle_id = ?, api_def_url = ?, is_default_bundle = ? WHERE api_def_id = ? AND bundle_id = ?`)
   151  
   152  	t.Run("success without bundleID", func(t *testing.T) {
   153  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   154  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   155  		apiBundleReferenceModel := fixAPIBundleReferenceModel()
   156  		apiBundleReferenceModel.BundleID = nil
   157  		apiBundleReferenceEntity := fixAPIBundleReferenceEntity()
   158  
   159  		convMock := &automock.BundleReferenceConverter{}
   160  		convMock.On("ToEntity", apiBundleReferenceModel).Return(apiBundleReferenceEntity, nil)
   161  		sqlMock.ExpectExec(updateQueryWithoutBundleID).
   162  			WithArgs(apiBundleReferenceEntity.APIDefID, apiBundleReferenceEntity.EventDefID, apiBundleReferenceEntity.APIDefaultTargetURL, apiBundleReferenceEntity.APIDefID).
   163  			WillReturnResult(sqlmock.NewResult(-1, 1))
   164  
   165  		pgRepository := bundlereferences.NewRepository(convMock)
   166  		// WHEN
   167  		err := pgRepository.Update(ctx, &apiBundleReferenceModel)
   168  		// THEN
   169  		require.NoError(t, err)
   170  		convMock.AssertExpectations(t)
   171  		sqlMock.AssertExpectations(t)
   172  	})
   173  	t.Run("success with bundleID", func(t *testing.T) {
   174  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   175  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   176  		apiBundleReferenceModel := fixAPIBundleReferenceModel()
   177  		apiBundleReferenceEntity := fixAPIBundleReferenceEntity()
   178  
   179  		convMock := &automock.BundleReferenceConverter{}
   180  		convMock.On("ToEntity", apiBundleReferenceModel).Return(apiBundleReferenceEntity, nil)
   181  		sqlMock.ExpectExec(updateQueryWithBundleID).
   182  			WithArgs(apiBundleReferenceEntity.APIDefID, apiBundleReferenceEntity.EventDefID, apiBundleReferenceEntity.BundleID, apiBundleReferenceEntity.APIDefaultTargetURL, apiBundleReferenceEntity.IsDefaultBundle, apiBundleReferenceEntity.APIDefID, apiBundleReferenceEntity.BundleID).
   183  			WillReturnResult(sqlmock.NewResult(-1, 1))
   184  
   185  		pgRepository := bundlereferences.NewRepository(convMock)
   186  
   187  		// WHEN
   188  		err := pgRepository.Update(ctx, &apiBundleReferenceModel)
   189  
   190  		// THEN
   191  		require.NoError(t, err)
   192  		convMock.AssertExpectations(t)
   193  		sqlMock.AssertExpectations(t)
   194  	})
   195  	t.Run("error when item is nil", func(t *testing.T) {
   196  		ctx := context.TODO()
   197  		convMock := automock.BundleReferenceConverter{}
   198  		pgRepository := bundlereferences.NewRepository(&convMock)
   199  
   200  		// WHEN
   201  		err := pgRepository.Update(ctx, nil)
   202  
   203  		// THEN
   204  		require.Error(t, err)
   205  		assert.Contains(t, err.Error(), "item cannot be nil")
   206  		convMock.AssertExpectations(t)
   207  	})
   208  }
   209  
   210  func TestPgRepository_DeleteByReferenceObjectID(t *testing.T) {
   211  	t.Run("success", func(t *testing.T) {
   212  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   213  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   214  		deleteQuery := `DELETE FROM public\.bundle_references WHERE api_def_id = \$1 AND bundle_id = \$2`
   215  
   216  		sqlMock.ExpectExec(deleteQuery).
   217  			WithArgs(apiDefID, bundleID).
   218  			WillReturnResult(sqlmock.NewResult(-1, 1))
   219  		convMock := &automock.BundleReferenceConverter{}
   220  		pgRepository := bundlereferences.NewRepository(convMock)
   221  
   222  		// WHEN
   223  		err := pgRepository.DeleteByReferenceObjectID(ctx, bundleID, model.BundleAPIReference, apiDefID)
   224  
   225  		// THEN
   226  		require.NoError(t, err)
   227  		sqlMock.AssertExpectations(t)
   228  		convMock.AssertExpectations(t)
   229  	})
   230  }
   231  
   232  func TestPgRepository_ListAllForBundle(t *testing.T) {
   233  	// GIVEN
   234  	inputCursor := ""
   235  	firstTargetURL := "https://test.com"
   236  	secondTargetURL := "https://test2.com"
   237  	firstBndlID := "111111111-1111-1111-1111-111111111111"
   238  	secondBndlID := "222222222-2222-2222-2222-222222222222"
   239  	firstAPIID := "333333333-3333-3333-3333-333333333333"
   240  	secondAPIID := "444444444-4444-4444-4444-444444444444"
   241  	firstEventID := "555555555-5555-5555-5555-555555555555"
   242  	secondEventID := "666666666-6666-6666-6666-666666666666"
   243  	scopesWithInternalVisibility := []string{"internal_visibility:read"}
   244  	scopesWithoutInternalVisibility := []string{"test:test"}
   245  	publicVisibility := "public"
   246  
   247  	firstAPIBndlRefEntity := fixAPIBundleReferenceEntityWithArgs(firstBndlID, firstAPIID, firstTargetURL)
   248  	secondAPIBndlRefEntity := fixAPIBundleReferenceEntityWithArgs(secondBndlID, secondAPIID, secondTargetURL)
   249  	firstEventBndlRefEntity := fixEventBundleReferenceEntityWithArgs(firstBndlID, firstEventID)
   250  	secondEventBndlRefEntity := fixEventBundleReferenceEntityWithArgs(secondBndlID, secondEventID)
   251  	bundleIDs := []string{firstBndlID, secondBndlID}
   252  
   253  	selectQueryForAPIs := `^\(SELECT (.+) FROM public\.bundle_references 
   254  		WHERE api_def_id IS NOT NULL AND bundle_id = \$1 ORDER BY api_def_id ASC, bundle_id ASC, api_def_url ASC LIMIT \$2 OFFSET \$3\) UNION 
   255  		\(SELECT (.+) FROM public\.bundle_references WHERE api_def_id IS NOT NULL AND bundle_id = \$4 ORDER BY api_def_id ASC, bundle_id ASC, api_def_url ASC LIMIT \$5 OFFSET \$6\)`
   256  
   257  	countQueryForAPIs := `SELECT bundle_id AS id, COUNT\(\*\) AS total_count FROM public.bundle_references WHERE api_def_id IS NOT NULL GROUP BY bundle_id ORDER BY bundle_id ASC`
   258  
   259  	selectQueryWithVisibilityCheckForAPIs := `^\(SELECT (.+) FROM public\.bundle_references 
   260  		WHERE api_def_id IN \(SELECT id FROM api_definitions WHERE visibility = \$1\) AND api_def_id IS NOT NULL AND bundle_id = \$2 ORDER BY api_def_id ASC, bundle_id ASC, api_def_url ASC LIMIT \$3 OFFSET \$4\) UNION 
   261  		\(SELECT (.+) FROM public\.bundle_references WHERE api_def_id IN \(SELECT id FROM api_definitions WHERE visibility = \$5\) AND api_def_id IS NOT NULL AND bundle_id = \$6 ORDER BY api_def_id ASC, bundle_id ASC, api_def_url ASC LIMIT \$7 OFFSET \$8\)`
   262  
   263  	countQueryWithVisibilityCheckForAPIs := `SELECT bundle_id AS id, COUNT\(\*\) AS total_count FROM public.bundle_references WHERE api_def_id IN \(SELECT id FROM api_definitions WHERE visibility = \$1\) AND api_def_id IS NOT NULL GROUP BY bundle_id ORDER BY bundle_id ASC`
   264  
   265  	// queries for Events
   266  
   267  	selectQueryForEvents := `^\(SELECT (.+) FROM public\.bundle_references 
   268  		WHERE event_def_id IS NOT NULL AND bundle_id = \$1 ORDER BY event_def_id ASC, bundle_id ASC LIMIT \$2 OFFSET \$3\) UNION 
   269  		\(SELECT (.+) FROM public\.bundle_references WHERE event_def_id IS NOT NULL AND bundle_id = \$4 ORDER BY event_def_id ASC, bundle_id ASC LIMIT \$5 OFFSET \$6\)`
   270  
   271  	countQueryForEvents := `SELECT bundle_id AS id, COUNT\(\*\) AS total_count FROM public.bundle_references WHERE event_def_id IS NOT NULL GROUP BY bundle_id ORDER BY bundle_id ASC`
   272  
   273  	selectQueryWithVisibilityCheckForEvents := `^\(SELECT (.+) FROM public\.bundle_references 
   274  		WHERE event_def_id IN \(SELECT id FROM event_api_definitions WHERE visibility = \$1\) AND event_def_id IS NOT NULL AND bundle_id = \$2 ORDER BY event_def_id ASC, bundle_id ASC LIMIT \$3 OFFSET \$4\) UNION 
   275  		\(SELECT (.+) FROM public\.bundle_references WHERE event_def_id IN \(SELECT id FROM event_api_definitions WHERE visibility = \$5\) AND event_def_id IS NOT NULL AND bundle_id = \$6 ORDER BY event_def_id ASC, bundle_id ASC LIMIT \$7 OFFSET \$8\)`
   276  
   277  	countQueryWithVisibilityCheckForEvents := `SELECT bundle_id AS id, COUNT\(\*\) AS total_count FROM public.bundle_references WHERE event_def_id IN \(SELECT id FROM event_api_definitions WHERE visibility = \$1\) AND event_def_id IS NOT NULL GROUP BY bundle_id ORDER BY bundle_id ASC`
   278  
   279  	t.Run("success when everything is returned for APIs when there is internal_visibility scope", func(t *testing.T) {
   280  		ExpectedLimit := 1
   281  		ExpectedOffset := 0
   282  		inputPageSize := 1
   283  
   284  		totalCountForFirstBundle := 1
   285  		totalCountForSecondBundle := 1
   286  
   287  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   288  
   289  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
   290  			AddRow(fixBundleReferenceRowWithoutEventIDWithArgs(firstBndlID, firstAPIID, firstTargetURL)...).
   291  			AddRow(fixBundleReferenceRowWithoutEventIDWithArgs(secondBndlID, secondAPIID, secondTargetURL)...)
   292  
   293  		sqlMock.ExpectQuery(selectQueryForAPIs).
   294  			WithArgs(firstBndlID, ExpectedLimit, ExpectedOffset, secondBndlID, ExpectedLimit, ExpectedOffset).
   295  			WillReturnRows(rows)
   296  
   297  		sqlMock.ExpectQuery(countQueryForAPIs).
   298  			WillReturnRows(sqlmock.NewRows([]string{"id", "total_count"}).
   299  				AddRow(firstBndlID, totalCountForFirstBundle).
   300  				AddRow(secondBndlID, totalCountForSecondBundle))
   301  
   302  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   303  		ctx = scope.SaveToContext(ctx, scopesWithInternalVisibility)
   304  		convMock := &automock.BundleReferenceConverter{}
   305  		convMock.On("FromEntity", firstAPIBndlRefEntity).Return(model.BundleReference{
   306  			BundleID:            str.Ptr(firstBndlID),
   307  			ObjectType:          model.BundleAPIReference,
   308  			ObjectID:            str.Ptr(firstAPIID),
   309  			APIDefaultTargetURL: str.Ptr(firstTargetURL),
   310  		}, nil)
   311  		convMock.On("FromEntity", secondAPIBndlRefEntity).Return(model.BundleReference{
   312  			BundleID:            str.Ptr(secondBndlID),
   313  			ObjectType:          model.BundleAPIReference,
   314  			ObjectID:            str.Ptr(secondAPIID),
   315  			APIDefaultTargetURL: str.Ptr(secondTargetURL),
   316  		}, nil)
   317  		pgRepository := bundlereferences.NewRepository(convMock)
   318  		// WHEN
   319  		modelBndlRefs, totalCounts, err := pgRepository.ListByBundleIDs(ctx, model.BundleAPIReference, bundleIDs, inputPageSize, inputCursor)
   320  		// THEN
   321  		require.NoError(t, err)
   322  		require.Len(t, modelBndlRefs, 2)
   323  		assert.Equal(t, firstBndlID, *modelBndlRefs[0].BundleID)
   324  		assert.Equal(t, secondBndlID, *modelBndlRefs[1].BundleID)
   325  		assert.Equal(t, firstAPIID, *modelBndlRefs[0].ObjectID)
   326  		assert.Equal(t, secondAPIID, *modelBndlRefs[1].ObjectID)
   327  		assert.Equal(t, firstTargetURL, *modelBndlRefs[0].APIDefaultTargetURL)
   328  		assert.Equal(t, secondTargetURL, *modelBndlRefs[1].APIDefaultTargetURL)
   329  		assert.Equal(t, totalCountForFirstBundle, totalCounts[firstBndlID])
   330  		assert.Equal(t, totalCountForSecondBundle, totalCounts[secondBndlID])
   331  		convMock.AssertExpectations(t)
   332  		sqlMock.AssertExpectations(t)
   333  	})
   334  
   335  	t.Run("success when there is no internal_visibility scope and result for APIs is filtered", func(t *testing.T) {
   336  		ExpectedLimit := 1
   337  		ExpectedOffset := 0
   338  		inputPageSize := 1
   339  
   340  		totalCountForFirstBundle := 0
   341  		totalCountForSecondBundle := 1
   342  
   343  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   344  
   345  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
   346  			AddRow(fixBundleReferenceRowWithoutEventIDWithArgs(secondBndlID, secondAPIID, secondTargetURL)...)
   347  
   348  		sqlMock.ExpectQuery(selectQueryWithVisibilityCheckForAPIs).
   349  			WithArgs(publicVisibility, firstBndlID, ExpectedLimit, ExpectedOffset, publicVisibility, secondBndlID, ExpectedLimit, ExpectedOffset).
   350  			WillReturnRows(rows)
   351  
   352  		sqlMock.ExpectQuery(countQueryWithVisibilityCheckForAPIs).
   353  			WithArgs(publicVisibility).
   354  			WillReturnRows(sqlmock.NewRows([]string{"id", "total_count"}).
   355  				AddRow(firstBndlID, totalCountForFirstBundle).
   356  				AddRow(secondBndlID, totalCountForSecondBundle))
   357  
   358  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   359  		ctx = scope.SaveToContext(ctx, scopesWithoutInternalVisibility)
   360  		convMock := &automock.BundleReferenceConverter{}
   361  		convMock.On("FromEntity", secondAPIBndlRefEntity).Return(model.BundleReference{
   362  			BundleID:            str.Ptr(secondBndlID),
   363  			ObjectType:          model.BundleAPIReference,
   364  			ObjectID:            str.Ptr(secondAPIID),
   365  			APIDefaultTargetURL: str.Ptr(secondTargetURL),
   366  		}, nil)
   367  		pgRepository := bundlereferences.NewRepository(convMock)
   368  		// WHEN
   369  		modelBndlRefs, totalCounts, err := pgRepository.ListByBundleIDs(ctx, model.BundleAPIReference, bundleIDs, inputPageSize, inputCursor)
   370  		// THEN
   371  		require.NoError(t, err)
   372  		require.Len(t, modelBndlRefs, 1)
   373  		assert.Equal(t, secondBndlID, *modelBndlRefs[0].BundleID)
   374  		assert.Equal(t, secondAPIID, *modelBndlRefs[0].ObjectID)
   375  		assert.Equal(t, secondTargetURL, *modelBndlRefs[0].APIDefaultTargetURL)
   376  		assert.Equal(t, totalCountForFirstBundle, totalCounts[firstBndlID])
   377  		assert.Equal(t, totalCountForSecondBundle, totalCounts[secondBndlID])
   378  		convMock.AssertExpectations(t)
   379  		sqlMock.AssertExpectations(t)
   380  	})
   381  
   382  	t.Run("success when everything is returned for Events when there is internal_visibility scope", func(t *testing.T) {
   383  		ExpectedLimit := 1
   384  		ExpectedOffset := 0
   385  		inputPageSize := 1
   386  
   387  		totalCountForFirstBundle := 1
   388  		totalCountForSecondBundle := 1
   389  
   390  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   391  
   392  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
   393  			AddRow(fixBundleReferenceRowWithoutAPIIDWithArgs(firstBndlID, firstEventID)...).
   394  			AddRow(fixBundleReferenceRowWithoutAPIIDWithArgs(secondBndlID, secondEventID)...)
   395  
   396  		sqlMock.ExpectQuery(selectQueryForEvents).
   397  			WithArgs(firstBndlID, ExpectedLimit, ExpectedOffset, secondBndlID, ExpectedLimit, ExpectedOffset).
   398  			WillReturnRows(rows)
   399  
   400  		sqlMock.ExpectQuery(countQueryForEvents).
   401  			WillReturnRows(sqlmock.NewRows([]string{"id", "total_count"}).
   402  				AddRow(firstBndlID, totalCountForFirstBundle).
   403  				AddRow(secondBndlID, totalCountForSecondBundle))
   404  
   405  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   406  		ctx = scope.SaveToContext(ctx, scopesWithInternalVisibility)
   407  		convMock := &automock.BundleReferenceConverter{}
   408  		convMock.On("FromEntity", firstEventBndlRefEntity).Return(model.BundleReference{
   409  			BundleID:   str.Ptr(firstBndlID),
   410  			ObjectType: model.BundleEventReference,
   411  			ObjectID:   str.Ptr(firstEventID),
   412  		}, nil)
   413  		convMock.On("FromEntity", secondEventBndlRefEntity).Return(model.BundleReference{
   414  			BundleID:   str.Ptr(secondBndlID),
   415  			ObjectType: model.BundleEventReference,
   416  			ObjectID:   str.Ptr(secondEventID),
   417  		}, nil)
   418  		pgRepository := bundlereferences.NewRepository(convMock)
   419  		// WHEN
   420  		modelBndlRefs, totalCounts, err := pgRepository.ListByBundleIDs(ctx, model.BundleEventReference, bundleIDs, inputPageSize, inputCursor)
   421  		// THEN
   422  		require.NoError(t, err)
   423  		require.Len(t, modelBndlRefs, 2)
   424  		assert.Equal(t, firstBndlID, *modelBndlRefs[0].BundleID)
   425  		assert.Equal(t, secondBndlID, *modelBndlRefs[1].BundleID)
   426  		assert.Equal(t, firstEventID, *modelBndlRefs[0].ObjectID)
   427  		assert.Equal(t, secondEventID, *modelBndlRefs[1].ObjectID)
   428  		assert.Equal(t, totalCountForFirstBundle, totalCounts[firstBndlID])
   429  		assert.Equal(t, totalCountForSecondBundle, totalCounts[secondBndlID])
   430  		convMock.AssertExpectations(t)
   431  		sqlMock.AssertExpectations(t)
   432  	})
   433  
   434  	t.Run("success when there is no internal_visibility scope and result for Events is filtered", func(t *testing.T) {
   435  		ExpectedLimit := 1
   436  		ExpectedOffset := 0
   437  		inputPageSize := 1
   438  
   439  		totalCountForFirstBundle := 0
   440  		totalCountForSecondBundle := 1
   441  
   442  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   443  
   444  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
   445  			AddRow(fixBundleReferenceRowWithoutAPIIDWithArgs(secondBndlID, secondEventID)...)
   446  
   447  		sqlMock.ExpectQuery(selectQueryWithVisibilityCheckForEvents).
   448  			WithArgs(publicVisibility, firstBndlID, ExpectedLimit, ExpectedOffset, publicVisibility, secondBndlID, ExpectedLimit, ExpectedOffset).
   449  			WillReturnRows(rows)
   450  
   451  		sqlMock.ExpectQuery(countQueryWithVisibilityCheckForEvents).
   452  			WithArgs(publicVisibility).
   453  			WillReturnRows(sqlmock.NewRows([]string{"id", "total_count"}).
   454  				AddRow(firstBndlID, totalCountForFirstBundle).
   455  				AddRow(secondBndlID, totalCountForSecondBundle))
   456  
   457  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   458  		ctx = scope.SaveToContext(ctx, scopesWithoutInternalVisibility)
   459  		convMock := &automock.BundleReferenceConverter{}
   460  		convMock.On("FromEntity", secondEventBndlRefEntity).Return(model.BundleReference{
   461  			BundleID:   str.Ptr(secondBndlID),
   462  			ObjectType: model.BundleEventReference,
   463  			ObjectID:   str.Ptr(secondEventID),
   464  		}, nil)
   465  		pgRepository := bundlereferences.NewRepository(convMock)
   466  		// WHEN
   467  		modelBndlRefs, totalCounts, err := pgRepository.ListByBundleIDs(ctx, model.BundleEventReference, bundleIDs, inputPageSize, inputCursor)
   468  		// THEN
   469  		require.NoError(t, err)
   470  		require.Len(t, modelBndlRefs, 1)
   471  		assert.Equal(t, secondBndlID, *modelBndlRefs[0].BundleID)
   472  		assert.Equal(t, secondEventID, *modelBndlRefs[0].ObjectID)
   473  		assert.Equal(t, totalCountForFirstBundle, totalCounts[firstBndlID])
   474  		assert.Equal(t, totalCountForSecondBundle, totalCounts[secondBndlID])
   475  		convMock.AssertExpectations(t)
   476  		sqlMock.AssertExpectations(t)
   477  	})
   478  
   479  	t.Run("success when there are more records", func(t *testing.T) {
   480  		ExpectedLimit := 1
   481  		ExpectedOffset := 0
   482  		inputPageSize := 1
   483  
   484  		totalCountForFirstBundle := 10
   485  		totalCountForSecondBundle := 10
   486  
   487  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   488  
   489  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
   490  			AddRow(fixBundleReferenceRowWithoutEventIDWithArgs(firstBndlID, firstAPIID, firstTargetURL)...).
   491  			AddRow(fixBundleReferenceRowWithoutEventIDWithArgs(secondBndlID, secondAPIID, secondTargetURL)...)
   492  
   493  		sqlMock.ExpectQuery(selectQueryForAPIs).
   494  			WithArgs(firstBndlID, ExpectedLimit, ExpectedOffset, secondBndlID, ExpectedLimit, ExpectedOffset).
   495  			WillReturnRows(rows)
   496  
   497  		sqlMock.ExpectQuery(countQueryForAPIs).
   498  			WillReturnRows(sqlmock.NewRows([]string{"id", "total_count"}).
   499  				AddRow(firstBndlID, totalCountForFirstBundle).
   500  				AddRow(secondBndlID, totalCountForSecondBundle))
   501  
   502  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   503  		ctx = scope.SaveToContext(ctx, scopesWithInternalVisibility)
   504  		convMock := &automock.BundleReferenceConverter{}
   505  		convMock.On("FromEntity", firstAPIBndlRefEntity).Return(model.BundleReference{
   506  			BundleID:            str.Ptr(firstBndlID),
   507  			ObjectType:          model.BundleAPIReference,
   508  			ObjectID:            str.Ptr(firstAPIID),
   509  			APIDefaultTargetURL: str.Ptr(firstTargetURL),
   510  		}, nil)
   511  		convMock.On("FromEntity", secondAPIBndlRefEntity).Return(model.BundleReference{
   512  			BundleID:            str.Ptr(secondBndlID),
   513  			ObjectType:          model.BundleAPIReference,
   514  			ObjectID:            str.Ptr(secondAPIID),
   515  			APIDefaultTargetURL: str.Ptr(secondTargetURL),
   516  		}, nil)
   517  		pgRepository := bundlereferences.NewRepository(convMock)
   518  		// WHEN
   519  		modelBndlRefs, totalCounts, err := pgRepository.ListByBundleIDs(ctx, model.BundleAPIReference, bundleIDs, inputPageSize, inputCursor)
   520  		// THEN
   521  		require.NoError(t, err)
   522  		require.Len(t, modelBndlRefs, 2)
   523  		assert.Equal(t, firstBndlID, *modelBndlRefs[0].BundleID)
   524  		assert.Equal(t, secondBndlID, *modelBndlRefs[1].BundleID)
   525  		assert.Equal(t, firstAPIID, *modelBndlRefs[0].ObjectID)
   526  		assert.Equal(t, secondAPIID, *modelBndlRefs[1].ObjectID)
   527  		assert.Equal(t, firstTargetURL, *modelBndlRefs[0].APIDefaultTargetURL)
   528  		assert.Equal(t, secondTargetURL, *modelBndlRefs[1].APIDefaultTargetURL)
   529  		assert.Equal(t, totalCountForFirstBundle, totalCounts[firstBndlID])
   530  		assert.Equal(t, totalCountForSecondBundle, totalCounts[secondBndlID])
   531  		convMock.AssertExpectations(t)
   532  		sqlMock.AssertExpectations(t)
   533  	})
   534  
   535  	t.Run("returns both public and internal/private Events when check for internal scope fails", func(t *testing.T) {
   536  		ExpectedLimit := 1
   537  		ExpectedOffset := 0
   538  		inputPageSize := 1
   539  
   540  		totalCountForFirstBundle := 1
   541  		totalCountForSecondBundle := 1
   542  
   543  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   544  
   545  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
   546  			AddRow(fixBundleReferenceRowWithoutAPIIDWithArgs(firstBndlID, firstEventID)...).
   547  			AddRow(fixBundleReferenceRowWithoutAPIIDWithArgs(secondBndlID, secondEventID)...)
   548  
   549  		sqlMock.ExpectQuery(selectQueryForEvents).
   550  			WithArgs(firstBndlID, ExpectedLimit, ExpectedOffset, secondBndlID, ExpectedLimit, ExpectedOffset).
   551  			WillReturnRows(rows)
   552  
   553  		sqlMock.ExpectQuery(countQueryForEvents).
   554  			WillReturnRows(sqlmock.NewRows([]string{"id", "total_count"}).
   555  				AddRow(firstBndlID, totalCountForFirstBundle).
   556  				AddRow(secondBndlID, totalCountForSecondBundle))
   557  
   558  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   559  		convMock := &automock.BundleReferenceConverter{}
   560  		convMock.On("FromEntity", firstEventBndlRefEntity).Return(model.BundleReference{
   561  			BundleID:   str.Ptr(firstBndlID),
   562  			ObjectType: model.BundleEventReference,
   563  			ObjectID:   str.Ptr(firstEventID),
   564  		}, nil)
   565  		convMock.On("FromEntity", secondEventBndlRefEntity).Return(model.BundleReference{
   566  			BundleID:   str.Ptr(secondBndlID),
   567  			ObjectType: model.BundleEventReference,
   568  			ObjectID:   str.Ptr(secondEventID),
   569  		}, nil)
   570  		pgRepository := bundlereferences.NewRepository(convMock)
   571  		// WHEN
   572  		modelBndlRefs, totalCounts, err := pgRepository.ListByBundleIDs(ctx, model.BundleEventReference, bundleIDs, inputPageSize, inputCursor)
   573  		// THEN
   574  		require.NoError(t, err)
   575  		require.Len(t, modelBndlRefs, 2)
   576  		assert.Equal(t, firstBndlID, *modelBndlRefs[0].BundleID)
   577  		assert.Equal(t, secondBndlID, *modelBndlRefs[1].BundleID)
   578  		assert.Equal(t, firstEventID, *modelBndlRefs[0].ObjectID)
   579  		assert.Equal(t, secondEventID, *modelBndlRefs[1].ObjectID)
   580  		assert.Equal(t, totalCountForFirstBundle, totalCounts[firstBndlID])
   581  		assert.Equal(t, totalCountForSecondBundle, totalCounts[secondBndlID])
   582  		convMock.AssertExpectations(t)
   583  		sqlMock.AssertExpectations(t)
   584  	})
   585  
   586  	t.Run("returns both public and internal/private APIs when check for internal scope fails", func(t *testing.T) {
   587  		ExpectedLimit := 1
   588  		ExpectedOffset := 0
   589  		inputPageSize := 1
   590  
   591  		totalCountForFirstBundle := 1
   592  		totalCountForSecondBundle := 1
   593  
   594  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   595  
   596  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
   597  			AddRow(fixBundleReferenceRowWithoutEventIDWithArgs(firstBndlID, firstAPIID, firstTargetURL)...).
   598  			AddRow(fixBundleReferenceRowWithoutEventIDWithArgs(secondBndlID, secondAPIID, secondTargetURL)...)
   599  
   600  		sqlMock.ExpectQuery(selectQueryForAPIs).
   601  			WithArgs(firstBndlID, ExpectedLimit, ExpectedOffset, secondBndlID, ExpectedLimit, ExpectedOffset).
   602  			WillReturnRows(rows)
   603  
   604  		sqlMock.ExpectQuery(countQueryForAPIs).
   605  			WillReturnRows(sqlmock.NewRows([]string{"id", "total_count"}).
   606  				AddRow(firstBndlID, totalCountForFirstBundle).
   607  				AddRow(secondBndlID, totalCountForSecondBundle))
   608  
   609  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   610  		convMock := &automock.BundleReferenceConverter{}
   611  		convMock.On("FromEntity", firstAPIBndlRefEntity).Return(model.BundleReference{
   612  			BundleID:            str.Ptr(firstBndlID),
   613  			ObjectType:          model.BundleAPIReference,
   614  			ObjectID:            str.Ptr(firstAPIID),
   615  			APIDefaultTargetURL: str.Ptr(firstTargetURL),
   616  		}, nil)
   617  		convMock.On("FromEntity", secondAPIBndlRefEntity).Return(model.BundleReference{
   618  			BundleID:            str.Ptr(secondBndlID),
   619  			ObjectType:          model.BundleAPIReference,
   620  			ObjectID:            str.Ptr(secondAPIID),
   621  			APIDefaultTargetURL: str.Ptr(secondTargetURL),
   622  		}, nil)
   623  		pgRepository := bundlereferences.NewRepository(convMock)
   624  		// WHEN
   625  		modelBndlRefs, totalCounts, err := pgRepository.ListByBundleIDs(ctx, model.BundleAPIReference, bundleIDs, inputPageSize, inputCursor)
   626  		// THEN
   627  		require.NoError(t, err)
   628  		require.Len(t, modelBndlRefs, 2)
   629  		assert.Equal(t, firstBndlID, *modelBndlRefs[0].BundleID)
   630  		assert.Equal(t, secondBndlID, *modelBndlRefs[1].BundleID)
   631  		assert.Equal(t, firstAPIID, *modelBndlRefs[0].ObjectID)
   632  		assert.Equal(t, secondAPIID, *modelBndlRefs[1].ObjectID)
   633  		assert.Equal(t, firstTargetURL, *modelBndlRefs[0].APIDefaultTargetURL)
   634  		assert.Equal(t, secondTargetURL, *modelBndlRefs[1].APIDefaultTargetURL)
   635  		assert.Equal(t, totalCountForFirstBundle, totalCounts[firstBndlID])
   636  		assert.Equal(t, totalCountForSecondBundle, totalCounts[secondBndlID])
   637  		convMock.AssertExpectations(t)
   638  		sqlMock.AssertExpectations(t)
   639  	})
   640  
   641  	t.Run("returns error when conversion from entity fails", func(t *testing.T) {
   642  		ExpectedLimit := 1
   643  		ExpectedOffset := 0
   644  		inputPageSize := 1
   645  		totalCountForFirstBundle := 1
   646  		totalCountForSecondBundle := 1
   647  
   648  		testErr := errors.New("test error")
   649  
   650  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   651  
   652  		rows := sqlmock.NewRows(fixBundleReferenceColumns()).
   653  			AddRow(fixBundleReferenceRowWithoutEventIDWithArgs(firstBndlID, firstAPIID, firstTargetURL)...).
   654  			AddRow(fixBundleReferenceRowWithoutEventIDWithArgs(secondBndlID, secondAPIID, secondTargetURL)...)
   655  
   656  		sqlMock.ExpectQuery(selectQueryForAPIs).
   657  			WithArgs(firstBndlID, ExpectedLimit, ExpectedOffset, secondBndlID, ExpectedLimit, ExpectedOffset).
   658  			WillReturnRows(rows)
   659  
   660  		sqlMock.ExpectQuery(countQueryForAPIs).
   661  			WillReturnRows(sqlmock.NewRows([]string{"id", "total_count"}).
   662  				AddRow(firstBndlID, totalCountForFirstBundle).
   663  				AddRow(secondBndlID, totalCountForSecondBundle))
   664  
   665  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   666  		ctx = scope.SaveToContext(ctx, scopesWithInternalVisibility)
   667  		convMock := &automock.BundleReferenceConverter{}
   668  		convMock.On("FromEntity", firstAPIBndlRefEntity).Return(model.BundleReference{}, testErr)
   669  		pgRepository := bundlereferences.NewRepository(convMock)
   670  		// WHEN
   671  		_, _, err := pgRepository.ListByBundleIDs(ctx, model.BundleAPIReference, bundleIDs, inputPageSize, inputCursor)
   672  		// THEN
   673  		require.Error(t, err)
   674  		require.Contains(t, err.Error(), testErr.Error())
   675  		convMock.AssertExpectations(t)
   676  		sqlMock.AssertExpectations(t)
   677  	})
   678  
   679  	t.Run("DB Error", func(t *testing.T) {
   680  		// GIVEN
   681  		inputPageSize := 1
   682  		ExpectedLimit := 1
   683  		ExpectedOffset := 0
   684  
   685  		pgRepository := bundlereferences.NewRepository(nil)
   686  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   687  		testError := errors.New("test error")
   688  
   689  		sqlMock.ExpectQuery(selectQueryForAPIs).
   690  			WithArgs(firstBndlID, ExpectedLimit, ExpectedOffset, secondBndlID, ExpectedLimit, ExpectedOffset).
   691  			WillReturnError(testError)
   692  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   693  		ctx = scope.SaveToContext(ctx, scopesWithInternalVisibility)
   694  
   695  		// WHEN
   696  		modelBndlRefs, totalCounts, err := pgRepository.ListByBundleIDs(ctx, model.BundleAPIReference, bundleIDs, inputPageSize, inputCursor)
   697  
   698  		// THEN
   699  		sqlMock.AssertExpectations(t)
   700  		assert.Nil(t, modelBndlRefs)
   701  		assert.Nil(t, totalCounts)
   702  		require.EqualError(t, err, "Internal Server Error: Unexpected error while executing SQL query")
   703  	})
   704  }