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

     1  package api_test
     2  
     3  import (
     4  	"context"
     5  	"database/sql/driver"
     6  	"regexp"
     7  	"testing"
     8  
     9  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    10  	"github.com/kyma-incubator/compass/components/director/pkg/str"
    11  
    12  	"github.com/kyma-incubator/compass/components/director/pkg/persistence"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/kyma-incubator/compass/components/director/pkg/pagination"
    16  
    17  	"github.com/DATA-DOG/go-sqlmock"
    18  	"github.com/kyma-incubator/compass/components/director/internal/domain/api"
    19  	"github.com/kyma-incubator/compass/components/director/internal/domain/api/automock"
    20  	"github.com/kyma-incubator/compass/components/director/internal/model"
    21  	"github.com/kyma-incubator/compass/components/director/internal/repo/testdb"
    22  )
    23  
    24  func TestPgRepository_GetByID(t *testing.T) {
    25  	entity := fixFullEntityAPIDefinitionWithAppID(apiDefID, "placeholder")
    26  	apiDefModel, _, _ := fixFullAPIDefinitionModelWithAppID("placeholder")
    27  
    28  	suite := testdb.RepoGetTestSuite{
    29  		Name: "Get API",
    30  		SQLQueryDetails: []testdb.SQLQueryDetails{
    31  			{
    32  				Query:    regexp.QuoteMeta(`SELECT id, app_id, app_template_version_id, package_id, name, description, group_name, ord_id, local_tenant_id, short_description, system_instance_aware, policy_level, custom_policy_level, api_protocol, tags, countries, links, api_resource_links, release_status, sunset_date, changelog_entries, labels, visibility, disabled, part_of_products, line_of_business, industry, version_value, version_deprecated, version_deprecated_since, version_for_removal, ready, created_at, updated_at, deleted_at, error, implementation_standard, custom_implementation_standard, custom_implementation_standard_description, target_urls, extensible, successors, resource_hash, hierarchy, supported_use_cases, documentation_labels FROM "public"."api_definitions" WHERE id = $1 AND (id IN (SELECT id FROM api_definitions_tenants WHERE tenant_id = $2))`),
    33  				Args:     []driver.Value{apiDefID, tenantID},
    34  				IsSelect: true,
    35  				ValidRowsProvider: func() []*sqlmock.Rows {
    36  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns()).AddRow(fixAPIDefinitionRow(apiDefID, "placeholder")...)}
    37  				},
    38  				InvalidRowsProvider: func() []*sqlmock.Rows {
    39  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns())}
    40  				},
    41  			},
    42  		},
    43  		ConverterMockProvider: func() testdb.Mock {
    44  			return &automock.APIDefinitionConverter{}
    45  		},
    46  		RepoConstructorFunc:       api.NewRepository,
    47  		ExpectedModelEntity:       &apiDefModel,
    48  		ExpectedDBEntity:          &entity,
    49  		MethodArgs:                []interface{}{tenantID, apiDefID},
    50  		DisableConverterErrorTest: true,
    51  	}
    52  
    53  	suite.Run(t)
    54  }
    55  
    56  func TestPgRepository_GetByIDGlobal(t *testing.T) {
    57  	entity := fixFullEntityAPIDefinitionWithAppID(apiDefID, "placeholder")
    58  	apiDefModel, _, _ := fixFullAPIDefinitionModelWithAppID("placeholder")
    59  
    60  	suite := testdb.RepoGetTestSuite{
    61  		Name: "Get Global API",
    62  		SQLQueryDetails: []testdb.SQLQueryDetails{
    63  			{
    64  				Query:    regexp.QuoteMeta(`SELECT id, app_id, app_template_version_id, package_id, name, description, group_name, ord_id, local_tenant_id, short_description, system_instance_aware, policy_level, custom_policy_level, api_protocol, tags, countries, links, api_resource_links, release_status, sunset_date, changelog_entries, labels, visibility, disabled, part_of_products, line_of_business, industry, version_value, version_deprecated, version_deprecated_since, version_for_removal, ready, created_at, updated_at, deleted_at, error, implementation_standard, custom_implementation_standard, custom_implementation_standard_description, target_urls, extensible, successors, resource_hash, hierarchy, supported_use_cases, documentation_labels FROM "public"."api_definitions" WHERE id = $1`),
    65  				Args:     []driver.Value{apiDefID},
    66  				IsSelect: true,
    67  				ValidRowsProvider: func() []*sqlmock.Rows {
    68  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns()).AddRow(fixAPIDefinitionRow(apiDefID, "placeholder")...)}
    69  				},
    70  				InvalidRowsProvider: func() []*sqlmock.Rows {
    71  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns())}
    72  				},
    73  			},
    74  		},
    75  		ConverterMockProvider: func() testdb.Mock {
    76  			return &automock.APIDefinitionConverter{}
    77  		},
    78  		RepoConstructorFunc:       api.NewRepository,
    79  		ExpectedModelEntity:       &apiDefModel,
    80  		ExpectedDBEntity:          &entity,
    81  		MethodName:                "GetByIDGlobal",
    82  		MethodArgs:                []interface{}{apiDefID},
    83  		DisableConverterErrorTest: true,
    84  	}
    85  
    86  	suite.Run(t)
    87  }
    88  
    89  func TestPgRepository_ListByResourceID(t *testing.T) {
    90  	entity1App := fixFullEntityAPIDefinitionWithAppID(apiDefID, "placeholder")
    91  	apiDefModel1App, _, _ := fixFullAPIDefinitionModelWithAppID("placeholder")
    92  	entity2App := fixFullEntityAPIDefinitionWithAppID(apiDefID, "placeholder2")
    93  	apiDefModel2App, _, _ := fixFullAPIDefinitionModelWithAppID("placeholder2")
    94  	entity1AppTemplateVersion := fixFullEntityAPIDefinitionWithAppTemplateVersionID(apiDefID, "placeholder")
    95  	apiDefModel1AppTemplateVersion, _, _ := fixFullAPIDefinitionModelWithAppTemplateVersionID("placeholder")
    96  	entity2AppTemplateVersion := fixFullEntityAPIDefinitionWithAppTemplateVersionID(apiDefID, "placeholder2")
    97  	apiDefModel2AppTemplateVersion, _, _ := fixFullAPIDefinitionModelWithAppTemplateVersionID("placeholder2")
    98  
    99  	suiteForApplication := testdb.RepoListTestSuite{
   100  		Name: "List APIs",
   101  		SQLQueryDetails: []testdb.SQLQueryDetails{
   102  			{
   103  				Query:    regexp.QuoteMeta(`SELECT id, app_id, app_template_version_id, package_id, name, description, group_name, ord_id, local_tenant_id, short_description, system_instance_aware, policy_level, custom_policy_level, api_protocol, tags, countries, links, api_resource_links, release_status, sunset_date, changelog_entries, labels, visibility, disabled, part_of_products, line_of_business, industry, version_value, version_deprecated, version_deprecated_since, version_for_removal, ready, created_at, updated_at, deleted_at, error, implementation_standard, custom_implementation_standard, custom_implementation_standard_description, target_urls, extensible, successors, resource_hash, hierarchy, supported_use_cases, documentation_labels FROM "public"."api_definitions" WHERE app_id = $1 AND (id IN (SELECT id FROM api_definitions_tenants WHERE tenant_id = $2)) FOR UPDATE`),
   104  				Args:     []driver.Value{appID, tenantID},
   105  				IsSelect: true,
   106  				ValidRowsProvider: func() []*sqlmock.Rows {
   107  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns()).AddRow(fixAPIDefinitionRow(apiDefID, "placeholder")...).AddRow(fixAPIDefinitionRow(apiDefID, "placeholder2")...)}
   108  				},
   109  				InvalidRowsProvider: func() []*sqlmock.Rows {
   110  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns())}
   111  				},
   112  			},
   113  		},
   114  		ConverterMockProvider: func() testdb.Mock {
   115  			return &automock.APIDefinitionConverter{}
   116  		},
   117  		RepoConstructorFunc:       api.NewRepository,
   118  		ExpectedModelEntities:     []interface{}{&apiDefModel1App, &apiDefModel2App},
   119  		ExpectedDBEntities:        []interface{}{&entity1App, &entity2App},
   120  		MethodArgs:                []interface{}{tenantID, resource.Application, appID},
   121  		MethodName:                "ListByResourceID",
   122  		DisableConverterErrorTest: true,
   123  	}
   124  
   125  	suiteForApplicationTemplateVersion := testdb.RepoListTestSuite{
   126  		Name: "List APIs",
   127  		SQLQueryDetails: []testdb.SQLQueryDetails{
   128  			{
   129  				Query: regexp.QuoteMeta(`SELECT id, app_id, app_template_version_id, package_id, name, description, group_name, ord_id, local_tenant_id, short_description, system_instance_aware, policy_level, custom_policy_level, api_protocol, tags, countries, links, api_resource_links, release_status, sunset_date, changelog_entries, labels, visibility, disabled, part_of_products, line_of_business, industry, version_value, version_deprecated, version_deprecated_since, version_for_removal, ready, created_at, updated_at, deleted_at, error, implementation_standard, custom_implementation_standard, custom_implementation_standard_description, target_urls, extensible, successors, resource_hash, hierarchy, supported_use_cases, documentation_labels FROM "public"."api_definitions" WHERE app_template_version_id = $1
   130                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       FOR UPDATE`),
   131  				Args:     []driver.Value{appTemplateVersionID},
   132  				IsSelect: true,
   133  				ValidRowsProvider: func() []*sqlmock.Rows {
   134  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns()).AddRow(fixAPIDefinitionRowForAppTemplateVersion(apiDefID, "placeholder")...).AddRow(fixAPIDefinitionRowForAppTemplateVersion(apiDefID, "placeholder2")...)}
   135  				},
   136  				InvalidRowsProvider: func() []*sqlmock.Rows {
   137  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns())}
   138  				},
   139  			},
   140  		},
   141  		ConverterMockProvider: func() testdb.Mock {
   142  			return &automock.APIDefinitionConverter{}
   143  		},
   144  		RepoConstructorFunc:       api.NewRepository,
   145  		ExpectedModelEntities:     []interface{}{&apiDefModel1AppTemplateVersion, &apiDefModel2AppTemplateVersion},
   146  		ExpectedDBEntities:        []interface{}{&entity1AppTemplateVersion, &entity2AppTemplateVersion},
   147  		MethodArgs:                []interface{}{tenantID, resource.ApplicationTemplateVersion, appTemplateVersionID},
   148  		MethodName:                "ListByResourceID",
   149  		DisableConverterErrorTest: true,
   150  	}
   151  
   152  	suiteForApplication.Run(t)
   153  	suiteForApplicationTemplateVersion.Run(t)
   154  }
   155  
   156  func TestPgRepository_ListByApplicationIDPage(t *testing.T) {
   157  	pageSize := 1
   158  	cursor := ""
   159  
   160  	firstAPIDefID := "firstAPIDefID"
   161  	firstAPIDef, _, _ := fixFullAPIDefinitionModelWithAppID("placeholder")
   162  	firstEntity := fixFullEntityAPIDefinitionWithAppID(firstAPIDefID, "placeholder")
   163  
   164  	suite := testdb.RepoListPageableTestSuite{
   165  		Name: "List APIs with paging",
   166  		SQLQueryDetails: []testdb.SQLQueryDetails{
   167  			{
   168  				Query:    regexp.QuoteMeta(`SELECT id, app_id, app_template_version_id, package_id, name, description, group_name, ord_id, local_tenant_id, short_description, system_instance_aware, policy_level, custom_policy_level, api_protocol, tags, countries, links, api_resource_links, release_status, sunset_date, changelog_entries, labels, visibility, disabled, part_of_products, line_of_business, industry, version_value, version_deprecated, version_deprecated_since, version_for_removal, ready, created_at, updated_at, deleted_at, error, implementation_standard, custom_implementation_standard, custom_implementation_standard_description, target_urls, extensible, successors, resource_hash, hierarchy, supported_use_cases, documentation_labels FROM "public"."api_definitions" WHERE (app_id = $1 AND (id IN (SELECT id FROM api_definitions_tenants WHERE tenant_id = $2)))`),
   169  				Args:     []driver.Value{appID, tenantID},
   170  				IsSelect: true,
   171  				ValidRowsProvider: func() []*sqlmock.Rows {
   172  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns()).AddRow(fixAPIDefinitionRow(firstAPIDefID, "placeholder")...)}
   173  				},
   174  			},
   175  			{
   176  				Query:    regexp.QuoteMeta(`SELECT COUNT(*) FROM "public"."api_definitions" WHERE (app_id = $1 AND (id IN (SELECT id FROM api_definitions_tenants WHERE tenant_id = $2)))`),
   177  				Args:     []driver.Value{appID, tenantID},
   178  				IsSelect: true,
   179  				ValidRowsProvider: func() []*sqlmock.Rows {
   180  					return []*sqlmock.Rows{sqlmock.NewRows([]string{"count"}).AddRow(1)}
   181  				},
   182  			},
   183  		},
   184  		Pages: []testdb.PageDetails{
   185  			{
   186  				ExpectedModelEntities: []interface{}{&firstAPIDef},
   187  				ExpectedDBEntities:    []interface{}{&firstEntity},
   188  				ExpectedPage: &model.APIDefinitionPage{
   189  					Data: []*model.APIDefinition{&firstAPIDef},
   190  					PageInfo: &pagination.Page{
   191  						StartCursor: "",
   192  						EndCursor:   "",
   193  						HasNextPage: false,
   194  					},
   195  					TotalCount: 1,
   196  				},
   197  			},
   198  		},
   199  		ConverterMockProvider: func() testdb.Mock {
   200  			return &automock.APIDefinitionConverter{}
   201  		},
   202  		RepoConstructorFunc:       api.NewRepository,
   203  		MethodName:                "ListByApplicationIDPage",
   204  		MethodArgs:                []interface{}{tenantID, appID, pageSize, cursor},
   205  		DisableConverterErrorTest: true,
   206  	}
   207  
   208  	suite.Run(t)
   209  }
   210  
   211  func TestPgRepository_ListAllForBundle(t *testing.T) {
   212  	pageSize := 1
   213  	cursor := ""
   214  
   215  	emptyPageBundleID := "emptyPageBundleID"
   216  
   217  	onePageBundleID := "onePageBundleID"
   218  	firstAPIDefID := "firstAPIDefID"
   219  	firstAPIDef, _, _ := fixFullAPIDefinitionModel(firstAPIDefID, "placeholder")
   220  	firstAPIDef.ApplicationID = str.Ptr(appID)
   221  
   222  	firstEntity := fixFullEntityAPIDefinitionWithAppID(firstAPIDefID, "placeholder")
   223  	firstBundleRef := fixModelBundleReference(onePageBundleID, firstAPIDefID)
   224  
   225  	multiplePagesBundleID := "multiplePagesBundleID"
   226  
   227  	secondAPIDefID := "secondAPIDefID"
   228  	secondAPIDef, _, _ := fixFullAPIDefinitionModel(secondAPIDefID, "placeholder")
   229  	secondAPIDef.ApplicationID = str.Ptr(appID)
   230  	secondEntity := fixFullEntityAPIDefinitionWithAppID(secondAPIDefID, "placeholder")
   231  	secondBundleRef := fixModelBundleReference(multiplePagesBundleID, secondAPIDefID)
   232  
   233  	totalCounts := map[string]int{
   234  		emptyPageBundleID:     0,
   235  		onePageBundleID:       1,
   236  		multiplePagesBundleID: 2,
   237  	}
   238  
   239  	suite := testdb.RepoListPageableTestSuite{
   240  		Name: "List APIs for multiple bundles with paging",
   241  		SQLQueryDetails: []testdb.SQLQueryDetails{
   242  			{
   243  				Query:    regexp.QuoteMeta(`SELECT id, app_id, app_template_version_id, package_id, name, description, group_name, ord_id, local_tenant_id, short_description, system_instance_aware, policy_level, custom_policy_level, api_protocol, tags, countries, links, api_resource_links, release_status, sunset_date, changelog_entries, labels, visibility, disabled, part_of_products, line_of_business, industry, version_value, version_deprecated, version_deprecated_since, version_for_removal, ready, created_at, updated_at, deleted_at, error, implementation_standard, custom_implementation_standard, custom_implementation_standard_description, target_urls, extensible, successors, resource_hash, hierarchy, supported_use_cases, documentation_labels FROM "public"."api_definitions" WHERE id IN ($1, $2) AND (id IN (SELECT id FROM api_definitions_tenants WHERE tenant_id = $3))`),
   244  				Args:     []driver.Value{firstAPIDefID, secondAPIDefID, tenantID},
   245  				IsSelect: true,
   246  				ValidRowsProvider: func() []*sqlmock.Rows {
   247  					return []*sqlmock.Rows{sqlmock.NewRows(fixAPIDefinitionColumns()).AddRow(fixAPIDefinitionRow(firstAPIDefID, "placeholder")...).AddRow(fixAPIDefinitionRow(secondAPIDefID, "placeholder")...)}
   248  				},
   249  			},
   250  		},
   251  		Pages: []testdb.PageDetails{
   252  			{
   253  				ExpectedModelEntities: nil,
   254  				ExpectedDBEntities:    nil,
   255  				ExpectedPage: &model.APIDefinitionPage{
   256  					Data: []*model.APIDefinition{},
   257  					PageInfo: &pagination.Page{
   258  						StartCursor: "",
   259  						EndCursor:   "",
   260  						HasNextPage: false,
   261  					},
   262  					TotalCount: 0,
   263  				},
   264  			},
   265  			{
   266  				ExpectedModelEntities: []interface{}{&firstAPIDef},
   267  				ExpectedDBEntities:    []interface{}{&firstEntity},
   268  				ExpectedPage: &model.APIDefinitionPage{
   269  					Data: []*model.APIDefinition{&firstAPIDef},
   270  					PageInfo: &pagination.Page{
   271  						StartCursor: "",
   272  						EndCursor:   "",
   273  						HasNextPage: false,
   274  					},
   275  					TotalCount: 1,
   276  				},
   277  			},
   278  			{
   279  				ExpectedModelEntities: []interface{}{&secondAPIDef},
   280  				ExpectedDBEntities:    []interface{}{&secondEntity},
   281  				ExpectedPage: &model.APIDefinitionPage{
   282  					Data: []*model.APIDefinition{&secondAPIDef},
   283  					PageInfo: &pagination.Page{
   284  						StartCursor: "",
   285  						EndCursor:   pagination.EncodeNextOffsetCursor(0, pageSize),
   286  						HasNextPage: true,
   287  					},
   288  					TotalCount: 2,
   289  				},
   290  			},
   291  		},
   292  		ConverterMockProvider: func() testdb.Mock {
   293  			return &automock.APIDefinitionConverter{}
   294  		},
   295  		RepoConstructorFunc: api.NewRepository,
   296  		MethodName:          "ListByBundleIDs",
   297  		MethodArgs: []interface{}{tenantID, []string{emptyPageBundleID, onePageBundleID, multiplePagesBundleID},
   298  			[]*model.BundleReference{firstBundleRef, secondBundleRef}, totalCounts, pageSize, cursor},
   299  		DisableConverterErrorTest: true,
   300  	}
   301  
   302  	suite.Run(t)
   303  }
   304  
   305  func TestPgRepository_Create(t *testing.T) {
   306  	var nilAPIDefModel *model.APIDefinition
   307  	apiDefModel, _, _ := fixFullAPIDefinitionModelWithAppID("placeholder")
   308  	apiDefEntity := fixFullEntityAPIDefinitionWithAppID(apiDefID, "placeholder")
   309  
   310  	suite := testdb.RepoCreateTestSuite{
   311  		Name: "Create API",
   312  		SQLQueryDetails: []testdb.SQLQueryDetails{
   313  			{
   314  				Query:    regexp.QuoteMeta("SELECT 1 FROM tenant_applications WHERE tenant_id = $1 AND id = $2 AND owner = $3"),
   315  				Args:     []driver.Value{tenantID, appID, true},
   316  				IsSelect: true,
   317  				ValidRowsProvider: func() []*sqlmock.Rows {
   318  					return []*sqlmock.Rows{testdb.RowWhenObjectExist()}
   319  				},
   320  				InvalidRowsProvider: func() []*sqlmock.Rows {
   321  					return []*sqlmock.Rows{testdb.RowWhenObjectDoesNotExist()}
   322  				},
   323  			},
   324  			{
   325  				Query:       `^INSERT INTO "public"."api_definitions" \(.+\) VALUES \(.+\)$`,
   326  				Args:        fixAPICreateArgs(apiDefID, &apiDefModel),
   327  				ValidResult: sqlmock.NewResult(-1, 1),
   328  			},
   329  		},
   330  		ConverterMockProvider: func() testdb.Mock {
   331  			return &automock.APIDefinitionConverter{}
   332  		},
   333  		RepoConstructorFunc:       api.NewRepository,
   334  		ModelEntity:               &apiDefModel,
   335  		DBEntity:                  &apiDefEntity,
   336  		NilModelEntity:            nilAPIDefModel,
   337  		TenantID:                  tenantID,
   338  		DisableConverterErrorTest: true,
   339  	}
   340  
   341  	suite.Run(t)
   342  }
   343  
   344  func TestPgRepository_CreateGlobal(t *testing.T) {
   345  	var nilAPIDefModel *model.APIDefinition
   346  	apiDefModel, _, _ := fixFullAPIDefinitionModelWithAppTemplateVersionID("placeholder")
   347  	apiDefEntity := fixFullEntityAPIDefinitionWithAppTemplateVersionID(apiDefID, "placeholder")
   348  
   349  	suite := testdb.RepoCreateTestSuite{
   350  		Name: "Create API",
   351  		SQLQueryDetails: []testdb.SQLQueryDetails{
   352  			{
   353  				Query:       `^INSERT INTO "public"."api_definitions" \(.+\) VALUES \(.+\)$`,
   354  				Args:        fixAPICreateArgsForAppTemplateVersion(apiDefID, &apiDefModel),
   355  				ValidResult: sqlmock.NewResult(-1, 1),
   356  			},
   357  		},
   358  		ConverterMockProvider: func() testdb.Mock {
   359  			return &automock.APIDefinitionConverter{}
   360  		},
   361  		RepoConstructorFunc:       api.NewRepository,
   362  		ModelEntity:               &apiDefModel,
   363  		DBEntity:                  &apiDefEntity,
   364  		NilModelEntity:            nilAPIDefModel,
   365  		IsGlobal:                  true,
   366  		MethodName:                "CreateGlobal",
   367  		DisableConverterErrorTest: true,
   368  	}
   369  
   370  	suite.Run(t)
   371  }
   372  
   373  func TestPgRepository_CreateMany(t *testing.T) {
   374  	insertQuery := `^INSERT INTO "public"."api_definitions" (.+) VALUES (.+)$`
   375  
   376  	t.Run("success", func(t *testing.T) {
   377  		sqlxDB, sqlMock := testdb.MockDatabase(t)
   378  		ctx := persistence.SaveToContext(context.TODO(), sqlxDB)
   379  		first, _, _ := fixFullAPIDefinitionModelWithAppID("first")
   380  		second, _, _ := fixFullAPIDefinitionModelWithAppID("second")
   381  		third, _, _ := fixFullAPIDefinitionModelWithAppID("third")
   382  		items := []*model.APIDefinition{&first, &second, &third}
   383  
   384  		convMock := &automock.APIDefinitionConverter{}
   385  		for _, item := range items {
   386  			ent := fixFullEntityAPIDefinitionWithAppID(item.ID, item.Name)
   387  			convMock.On("ToEntity", item).Return(&ent, nil).Once()
   388  			sqlMock.ExpectQuery(regexp.QuoteMeta("SELECT 1 FROM tenant_applications WHERE tenant_id = $1 AND id = $2 AND owner = $3")).
   389  				WithArgs(tenantID, appID, true).WillReturnRows(testdb.RowWhenObjectExist())
   390  			sqlMock.ExpectExec(insertQuery).
   391  				WithArgs(fixAPICreateArgs(item.ID, item)...).
   392  				WillReturnResult(sqlmock.NewResult(-1, 1))
   393  		}
   394  		pgRepository := api.NewRepository(convMock)
   395  		// WHEN
   396  		err := pgRepository.CreateMany(ctx, tenantID, items)
   397  		// THEN
   398  		require.NoError(t, err)
   399  		convMock.AssertExpectations(t)
   400  		sqlMock.AssertExpectations(t)
   401  	})
   402  }
   403  
   404  func TestPgRepository_Update(t *testing.T) {
   405  	updateQuery := regexp.QuoteMeta(`UPDATE "public"."api_definitions" SET package_id = ?, name = ?, description = ?, group_name = ?, ord_id = ?, local_tenant_id = ?,
   406  		short_description = ?, system_instance_aware = ?, policy_level = ?, custom_policy_level = ?, api_protocol = ?, tags = ?, countries = ?, links = ?, api_resource_links = ?, release_status = ?,
   407  		sunset_date = ?, changelog_entries = ?, labels = ?, visibility = ?, disabled = ?, part_of_products = ?, line_of_business = ?,
   408  		industry = ?, version_value = ?, version_deprecated = ?, version_deprecated_since = ?, version_for_removal = ?, ready = ?, created_at = ?,
   409  		updated_at = ?, deleted_at = ?, error = ?, implementation_standard = ?, custom_implementation_standard = ?, custom_implementation_standard_description = ?,
   410  		target_urls = ?, extensible = ?, successors = ?, resource_hash = ?, hierarchy = ?, supported_use_cases = ?, documentation_labels = ?
   411  		WHERE id = ? AND (id IN (SELECT id FROM api_definitions_tenants WHERE tenant_id = ? AND owner = true))`)
   412  
   413  	var nilAPIDefModel *model.APIDefinition
   414  	apiModel, _, _ := fixFullAPIDefinitionModelWithAppID("update")
   415  	entity := fixFullEntityAPIDefinitionWithAppID(apiDefID, "update")
   416  	entity.UpdatedAt = &fixedTimestamp
   417  	entity.DeletedAt = &fixedTimestamp // This is needed as workaround so that updatedAt timestamp is not updated
   418  
   419  	suite := testdb.RepoUpdateTestSuite{
   420  		Name: "Update API",
   421  		SQLQueryDetails: []testdb.SQLQueryDetails{
   422  			{
   423  				Query: updateQuery,
   424  				Args: []driver.Value{entity.PackageID, entity.Name, entity.Description, entity.Group,
   425  					entity.OrdID, entity.LocalTenantID, entity.ShortDescription, entity.SystemInstanceAware, entity.PolicyLevel, entity.CustomPolicyLevel, entity.APIProtocol, entity.Tags, entity.Countries,
   426  					entity.Links, entity.APIResourceLinks, entity.ReleaseStatus, entity.SunsetDate, entity.ChangeLogEntries, entity.Labels, entity.Visibility,
   427  					entity.Disabled, entity.PartOfProducts, entity.LineOfBusiness, entity.Industry, entity.Version.Value, entity.Version.Deprecated,
   428  					entity.Version.DeprecatedSince, entity.Version.ForRemoval, entity.Ready, entity.CreatedAt, entity.UpdatedAt, entity.DeletedAt,
   429  					entity.Error, entity.ImplementationStandard, entity.CustomImplementationStandard, entity.CustomImplementationStandardDescription,
   430  					entity.TargetURLs, entity.Extensible, entity.Successors, entity.ResourceHash, entity.Hierarchy, entity.SupportedUseCases, entity.DocumentationLabels, entity.ID, tenantID},
   431  				ValidResult:   sqlmock.NewResult(-1, 1),
   432  				InvalidResult: sqlmock.NewResult(-1, 0),
   433  			},
   434  		},
   435  		ConverterMockProvider: func() testdb.Mock {
   436  			return &automock.APIDefinitionConverter{}
   437  		},
   438  		RepoConstructorFunc:       api.NewRepository,
   439  		ModelEntity:               &apiModel,
   440  		DBEntity:                  &entity,
   441  		NilModelEntity:            nilAPIDefModel,
   442  		TenantID:                  tenantID,
   443  		DisableConverterErrorTest: true,
   444  	}
   445  
   446  	suite.Run(t)
   447  }
   448  
   449  func TestPgRepository_UpdateGlobal(t *testing.T) {
   450  	updateQuery := regexp.QuoteMeta(`UPDATE "public"."api_definitions" SET package_id = ?, name = ?, description = ?, group_name = ?, ord_id = ?, local_tenant_id = ?,
   451  		short_description = ?, system_instance_aware = ?, policy_level = ?, custom_policy_level = ?, api_protocol = ?, tags = ?, countries = ?, links = ?, api_resource_links = ?, release_status = ?,
   452  		sunset_date = ?, changelog_entries = ?, labels = ?, visibility = ?, disabled = ?, part_of_products = ?, line_of_business = ?,
   453  		industry = ?, version_value = ?, version_deprecated = ?, version_deprecated_since = ?, version_for_removal = ?, ready = ?, created_at = ?,
   454  		updated_at = ?, deleted_at = ?, error = ?, implementation_standard = ?, custom_implementation_standard = ?, custom_implementation_standard_description = ?,
   455  		target_urls = ?, extensible = ?, successors = ?, resource_hash = ?, hierarchy = ?, supported_use_cases = ?, documentation_labels = ?
   456  		WHERE id = ?`)
   457  
   458  	var nilAPIDefModel *model.APIDefinition
   459  	apiModel, _, _ := fixFullAPIDefinitionModelWithAppID("update")
   460  	entity := fixFullEntityAPIDefinitionWithAppID(apiDefID, "update")
   461  	entity.UpdatedAt = &fixedTimestamp
   462  	entity.DeletedAt = &fixedTimestamp // This is needed as workaround so that updatedAt timestamp is not updated
   463  
   464  	suite := testdb.RepoUpdateTestSuite{
   465  		Name: "Update Global API Global",
   466  		SQLQueryDetails: []testdb.SQLQueryDetails{
   467  			{
   468  				Query: updateQuery,
   469  				Args: []driver.Value{entity.PackageID, entity.Name, entity.Description, entity.Group,
   470  					entity.OrdID, entity.LocalTenantID, entity.ShortDescription, entity.SystemInstanceAware, entity.PolicyLevel, entity.CustomPolicyLevel, entity.APIProtocol, entity.Tags, entity.Countries,
   471  					entity.Links, entity.APIResourceLinks, entity.ReleaseStatus, entity.SunsetDate, entity.ChangeLogEntries, entity.Labels, entity.Visibility,
   472  					entity.Disabled, entity.PartOfProducts, entity.LineOfBusiness, entity.Industry, entity.Version.Value, entity.Version.Deprecated,
   473  					entity.Version.DeprecatedSince, entity.Version.ForRemoval, entity.Ready, entity.CreatedAt, entity.UpdatedAt, entity.DeletedAt,
   474  					entity.Error, entity.ImplementationStandard, entity.CustomImplementationStandard, entity.CustomImplementationStandardDescription,
   475  					entity.TargetURLs, entity.Extensible, entity.Successors, entity.ResourceHash, entity.Hierarchy, entity.SupportedUseCases, entity.DocumentationLabels, entity.ID},
   476  				ValidResult:   sqlmock.NewResult(-1, 1),
   477  				InvalidResult: sqlmock.NewResult(-1, 0),
   478  			},
   479  		},
   480  		ConverterMockProvider: func() testdb.Mock {
   481  			return &automock.APIDefinitionConverter{}
   482  		},
   483  		RepoConstructorFunc:       api.NewRepository,
   484  		ModelEntity:               &apiModel,
   485  		DBEntity:                  &entity,
   486  		NilModelEntity:            nilAPIDefModel,
   487  		DisableConverterErrorTest: true,
   488  		UpdateMethodName:          "UpdateGlobal",
   489  		IsGlobal:                  true,
   490  	}
   491  
   492  	suite.Run(t)
   493  }
   494  
   495  func TestPgRepository_Delete(t *testing.T) {
   496  	suite := testdb.RepoDeleteTestSuite{
   497  		Name: "API Delete",
   498  		SQLQueryDetails: []testdb.SQLQueryDetails{
   499  			{
   500  				Query:         regexp.QuoteMeta(`DELETE FROM "public"."api_definitions" WHERE id = $1 AND (id IN (SELECT id FROM api_definitions_tenants WHERE tenant_id = $2 AND owner = true))`),
   501  				Args:          []driver.Value{apiDefID, tenantID},
   502  				ValidResult:   sqlmock.NewResult(-1, 1),
   503  				InvalidResult: sqlmock.NewResult(-1, 2),
   504  			},
   505  		},
   506  		ConverterMockProvider: func() testdb.Mock {
   507  			return &automock.APIDefinitionConverter{}
   508  		},
   509  		RepoConstructorFunc: api.NewRepository,
   510  		MethodArgs:          []interface{}{tenantID, apiDefID},
   511  	}
   512  
   513  	suite.Run(t)
   514  }
   515  
   516  func TestPgRepository_DeleteGlobal(t *testing.T) {
   517  	suite := testdb.RepoDeleteTestSuite{
   518  		Name: "API Delete Global",
   519  		SQLQueryDetails: []testdb.SQLQueryDetails{
   520  			{
   521  				Query:         regexp.QuoteMeta(`DELETE FROM "public"."api_definitions" WHERE id = $1`),
   522  				Args:          []driver.Value{apiDefID},
   523  				ValidResult:   sqlmock.NewResult(-1, 1),
   524  				InvalidResult: sqlmock.NewResult(-1, 2),
   525  			},
   526  		},
   527  		ConverterMockProvider: func() testdb.Mock {
   528  			return &automock.APIDefinitionConverter{}
   529  		},
   530  		RepoConstructorFunc: api.NewRepository,
   531  		MethodArgs:          []interface{}{apiDefID},
   532  		IsGlobal:            true,
   533  		MethodName:          "DeleteGlobal",
   534  	}
   535  
   536  	suite.Run(t)
   537  }
   538  
   539  func TestPgRepository_DeleteAllByBundleID(t *testing.T) {
   540  	suite := testdb.RepoDeleteTestSuite{
   541  		Name: "API Delete By BundleID",
   542  		SQLQueryDetails: []testdb.SQLQueryDetails{
   543  			{
   544  				Query:         regexp.QuoteMeta(`DELETE FROM "public"."api_definitions" WHERE id IN (SELECT api_def_id FROM public.bundle_references WHERE bundle_id = $1 AND api_def_id IS NOT NULL) AND (id IN (SELECT id FROM api_definitions_tenants WHERE tenant_id = $2 AND owner = true))`),
   545  				Args:          []driver.Value{bundleID, tenantID},
   546  				ValidResult:   sqlmock.NewResult(-1, 1),
   547  				InvalidResult: sqlmock.NewResult(-1, 2),
   548  			},
   549  		},
   550  		ConverterMockProvider: func() testdb.Mock {
   551  			return &automock.APIDefinitionConverter{}
   552  		},
   553  		RepoConstructorFunc: api.NewRepository,
   554  		MethodName:          "DeleteAllByBundleID",
   555  		MethodArgs:          []interface{}{tenantID, bundleID},
   556  		IsDeleteMany:        true,
   557  	}
   558  
   559  	suite.Run(t)
   560  }
   561  
   562  func TestPgRepository_Exists(t *testing.T) {
   563  	suite := testdb.RepoExistTestSuite{
   564  		Name: "API Exists",
   565  		SQLQueryDetails: []testdb.SQLQueryDetails{
   566  			{
   567  				Query:    regexp.QuoteMeta(`SELECT 1 FROM "public"."api_definitions" WHERE id = $1 AND (id IN (SELECT id FROM api_definitions_tenants WHERE tenant_id = $2))`),
   568  				Args:     []driver.Value{apiDefID, tenantID},
   569  				IsSelect: true,
   570  				ValidRowsProvider: func() []*sqlmock.Rows {
   571  					return []*sqlmock.Rows{testdb.RowWhenObjectExist()}
   572  				},
   573  				InvalidRowsProvider: func() []*sqlmock.Rows {
   574  					return []*sqlmock.Rows{testdb.RowWhenObjectDoesNotExist()}
   575  				},
   576  			},
   577  		},
   578  		ConverterMockProvider: func() testdb.Mock {
   579  			return &automock.APIDefinitionConverter{}
   580  		},
   581  		RepoConstructorFunc: api.NewRepository,
   582  		TargetID:            apiDefID,
   583  		TenantID:            tenantID,
   584  		MethodName:          "Exists",
   585  		MethodArgs:          []interface{}{tenantID, apiDefID},
   586  	}
   587  
   588  	suite.Run(t)
   589  }