github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/repo/get_test.go (about) 1 package repo_test 2 3 import ( 4 "context" 5 "fmt" 6 "regexp" 7 "testing" 8 "time" 9 10 "github.com/DATA-DOG/go-sqlmock" 11 "github.com/kyma-incubator/compass/components/director/internal/repo" 12 "github.com/kyma-incubator/compass/components/director/internal/repo/testdb" 13 "github.com/kyma-incubator/compass/components/director/pkg/apperrors" 14 "github.com/kyma-incubator/compass/components/director/pkg/persistence" 15 "github.com/kyma-incubator/compass/components/director/pkg/resource" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 ) 19 20 func TestGetSingle(t *testing.T) { 21 sut := repo.NewSingleGetter(appTableName, appColumns) 22 resourceType := resource.Application 23 m2mTable, ok := resourceType.TenantAccessTable() 24 require.True(t, ok) 25 26 t.Run("success", func(t *testing.T) { 27 // GIVEN 28 db, mock := testdb.MockDatabase(t) 29 ctx := persistence.SaveToContext(context.TODO(), db) 30 defer mock.AssertExpectations(t) 31 32 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE id = $1 AND %s", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$2"))) 33 rows := sqlmock.NewRows([]string{"id", "name", "description"}).AddRow(appID, appName, appDescription) 34 mock.ExpectQuery(expectedQuery).WithArgs(appID, tenantID).WillReturnRows(rows) 35 dest := App{} 36 // WHEN 37 err := sut.Get(ctx, resourceType, tenantID, repo.Conditions{repo.NewEqualCondition("id", appID)}, repo.NoOrderBy, &dest) 38 // THEN 39 require.NoError(t, err) 40 assert.Equal(t, appID, dest.ID) 41 assert.Equal(t, appName, dest.Name) 42 assert.Equal(t, appDescription, dest.Description) 43 }) 44 45 t.Run("success when no conditions", func(t *testing.T) { 46 // GIVEN 47 db, mock := testdb.MockDatabase(t) 48 ctx := persistence.SaveToContext(context.TODO(), db) 49 defer mock.AssertExpectations(t) 50 51 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE %s", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$1"))) 52 rows := sqlmock.NewRows([]string{"id", "name", "description"}).AddRow(appID, appName, appDescription) 53 mock.ExpectQuery(expectedQuery).WithArgs(tenantID).WillReturnRows(rows) 54 dest := App{} 55 // WHEN 56 err := sut.Get(ctx, resourceType, tenantID, nil, repo.NoOrderBy, &dest) 57 // THEN 58 require.NoError(t, err) 59 assert.Equal(t, appID, dest.ID) 60 assert.Equal(t, appName, dest.Name) 61 assert.Equal(t, appDescription, dest.Description) 62 }) 63 64 t.Run("success when more conditions", func(t *testing.T) { 65 db, mock := testdb.MockDatabase(t) 66 ctx := persistence.SaveToContext(context.TODO(), db) 67 defer mock.AssertExpectations(t) 68 69 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE id = $1 AND name = $2 AND %s", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$3"))) 70 rows := sqlmock.NewRows([]string{"id", "name", "description"}).AddRow(appID, appName, appDescription) 71 mock.ExpectQuery(expectedQuery).WithArgs(appID, appName, tenantID).WillReturnRows(rows) 72 dest := App{} 73 // WHEN 74 err := sut.Get(ctx, resourceType, tenantID, repo.Conditions{repo.NewEqualCondition("id", appID), repo.NewEqualCondition("name", appName)}, repo.NoOrderBy, &dest) 75 // THEN 76 require.NoError(t, err) 77 assert.Equal(t, appID, dest.ID) 78 assert.Equal(t, appName, dest.Name) 79 assert.Equal(t, appDescription, dest.Description) 80 }) 81 82 t.Run("success when IN condition", func(t *testing.T) { 83 db, mock := testdb.MockDatabase(t) 84 ctx := persistence.SaveToContext(context.TODO(), db) 85 defer mock.AssertExpectations(t) 86 87 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE name IN (SELECT name from names WHERE description = $1 AND id = $2) AND %s", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$3"))) 88 rows := sqlmock.NewRows([]string{"id", "name", "description"}).AddRow(appID, appName, appDescription) 89 mock.ExpectQuery(expectedQuery).WithArgs("foo", 3, tenantID).WillReturnRows(rows) 90 dest := App{} 91 // WHEN 92 err := sut.Get(ctx, resourceType, tenantID, repo.Conditions{repo.NewInConditionForSubQuery("name", "SELECT name from names WHERE description = ? AND id = ?", []interface{}{"foo", 3})}, repo.NoOrderBy, &dest) 93 // THEN 94 require.NoError(t, err) 95 assert.Equal(t, appID, dest.ID) 96 assert.Equal(t, appName, dest.Name) 97 assert.Equal(t, appDescription, dest.Description) 98 }) 99 100 t.Run("success when IN condition for values", func(t *testing.T) { 101 db, mock := testdb.MockDatabase(t) 102 ctx := persistence.SaveToContext(context.TODO(), db) 103 defer mock.AssertExpectations(t) 104 105 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE name IN ($1, $2) AND %s", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$3"))) 106 rows := sqlmock.NewRows([]string{"id", "name", "description"}).AddRow(appID, appName, appDescription) 107 mock.ExpectQuery(expectedQuery).WithArgs("foo", "bar", tenantID).WillReturnRows(rows) 108 dest := App{} 109 // WHEN 110 err := sut.Get(ctx, resourceType, tenantID, repo.Conditions{repo.NewInConditionForStringValues("name", []string{"foo", "bar"})}, repo.NoOrderBy, &dest) 111 // THEN 112 require.NoError(t, err) 113 assert.Equal(t, appID, dest.ID) 114 assert.Equal(t, appName, dest.Name) 115 assert.Equal(t, appDescription, dest.Description) 116 }) 117 118 t.Run("success with order by params", func(t *testing.T) { 119 // GIVEN 120 db, mock := testdb.MockDatabase(t) 121 ctx := persistence.SaveToContext(context.TODO(), db) 122 defer mock.AssertExpectations(t) 123 124 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE %s ORDER BY name ASC", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$1"))) 125 rows := sqlmock.NewRows([]string{"id", "name", "description"}).AddRow(appID, appName, appDescription) 126 mock.ExpectQuery(expectedQuery).WithArgs(tenantID).WillReturnRows(rows) 127 dest := App{} 128 // WHEN 129 err := sut.Get(ctx, resourceType, tenantID, nil, repo.OrderByParams{repo.NewAscOrderBy("name")}, &dest) 130 // THEN 131 require.NoError(t, err) 132 assert.Equal(t, appID, dest.ID) 133 assert.Equal(t, appName, dest.Name) 134 assert.Equal(t, appDescription, dest.Description) 135 }) 136 137 t.Run("success with multiple order by params", func(t *testing.T) { 138 // GIVEN 139 db, mock := testdb.MockDatabase(t) 140 ctx := persistence.SaveToContext(context.TODO(), db) 141 defer mock.AssertExpectations(t) 142 143 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE %s ORDER BY name ASC, description DESC", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$1"))) 144 rows := sqlmock.NewRows([]string{"id", "name", "description"}).AddRow(appID, appName, appDescription) 145 mock.ExpectQuery(expectedQuery).WithArgs(tenantID).WillReturnRows(rows) 146 dest := App{} 147 // WHEN 148 err := sut.Get(ctx, resourceType, tenantID, nil, repo.OrderByParams{repo.NewAscOrderBy("name"), repo.NewDescOrderBy("description")}, &dest) 149 // THEN 150 require.NoError(t, err) 151 assert.Equal(t, appID, dest.ID) 152 assert.Equal(t, appName, dest.Name) 153 assert.Equal(t, appDescription, dest.Description) 154 }) 155 156 t.Run("success with conditions and order by params", func(t *testing.T) { 157 // GIVEN 158 db, mock := testdb.MockDatabase(t) 159 ctx := persistence.SaveToContext(context.TODO(), db) 160 defer mock.AssertExpectations(t) 161 162 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE name = $1 AND description = $2 AND %s ORDER BY name ASC", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$3"))) 163 rows := sqlmock.NewRows([]string{"id", "name", "description"}).AddRow(appID, appName, appDescription) 164 mock.ExpectQuery(expectedQuery).WithArgs(appName, appDescription, tenantID).WillReturnRows(rows) 165 dest := App{} 166 // WHEN 167 err := sut.Get(ctx, resourceType, tenantID, repo.Conditions{repo.NewEqualCondition("name", appName), repo.NewEqualCondition("description", appDescription)}, repo.OrderByParams{repo.NewAscOrderBy("name"), repo.NewDescOrderBy("description")}, &dest) 168 // THEN 169 require.NoError(t, err) 170 assert.Equal(t, appID, dest.ID) 171 assert.Equal(t, appName, dest.Name) 172 assert.Equal(t, appDescription, dest.Description) 173 }) 174 175 t.Run("returns error when operation on db failed", func(t *testing.T) { 176 // GIVEN 177 db, mock := testdb.MockDatabase(t) 178 ctx := persistence.SaveToContext(context.TODO(), db) 179 defer mock.AssertExpectations(t) 180 181 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE id = $1 AND %s", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$2"))) 182 mock.ExpectQuery(expectedQuery).WithArgs(appID, tenantID).WillReturnError(someError()) 183 dest := App{} 184 // WHEN 185 err := sut.Get(ctx, resourceType, tenantID, repo.Conditions{repo.NewEqualCondition("id", appID)}, repo.NoOrderBy, &dest) 186 // THEN 187 require.EqualError(t, err, "Internal Server Error: Unexpected error while executing SQL query") 188 }) 189 190 t.Run("context properly canceled", func(t *testing.T) { 191 db, mock := testdb.MockDatabase(t) 192 defer mock.AssertExpectations(t) 193 194 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Nanosecond) 195 defer cancel() 196 197 ctx = persistence.SaveToContext(ctx, db) 198 dest := App{} 199 200 err := sut.Get(ctx, resourceType, tenantID, repo.Conditions{repo.NewEqualCondition("id", appID)}, repo.NoOrderBy, &dest) 201 202 require.EqualError(t, err, "Internal Server Error: Maximum processing timeout reached") 203 }) 204 205 t.Run("returns ErrorNotFound if object not found", func(t *testing.T) { 206 // GIVEN 207 db, mock := testdb.MockDatabase(t) 208 ctx := persistence.SaveToContext(context.TODO(), db) 209 defer mock.AssertExpectations(t) 210 noRows := sqlmock.NewRows([]string{"id", "name", "description"}) 211 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE id = $1 AND %s", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$2"))) 212 mock.ExpectQuery(expectedQuery).WithArgs(appID, tenantID).WillReturnRows(noRows) 213 dest := App{} 214 // WHEN 215 err := sut.Get(ctx, resourceType, tenantID, repo.Conditions{repo.NewEqualCondition("id", appID)}, repo.NoOrderBy, &dest) 216 // THEN 217 require.NotNil(t, err) 218 assert.True(t, apperrors.IsNotFoundError(err)) 219 }) 220 221 t.Run("returns error if entity does not have tenant access table", func(t *testing.T) { 222 db, mock := testdb.MockDatabase(t) 223 ctx := persistence.SaveToContext(context.TODO(), db) 224 defer mock.AssertExpectations(t) 225 226 err := sut.Get(ctx, UserType, tenantID, nil, repo.NoOrderBy, &User{}) 227 require.EqualError(t, err, "entity UserType does not have access table") 228 }) 229 230 t.Run("returns error if empty tenant id", func(t *testing.T) { 231 db, mock := testdb.MockDatabase(t) 232 ctx := persistence.SaveToContext(context.TODO(), db) 233 defer mock.AssertExpectations(t) 234 235 err := sut.Get(ctx, resourceType, "", nil, repo.NoOrderBy, &User{}) 236 require.EqualError(t, err, apperrors.NewTenantRequiredError().Error()) 237 }) 238 239 t.Run("returns error if missing persistence context", func(t *testing.T) { 240 ctx := context.TODO() 241 err := sut.Get(ctx, resourceType, tenantID, repo.Conditions{repo.NewEqualCondition("id", appID)}, repo.NoOrderBy, &User{}) 242 require.EqualError(t, err, apperrors.NewInternalError("unable to fetch database from context").Error()) 243 }) 244 245 t.Run("returns error if destination is nil", func(t *testing.T) { 246 err := sut.Get(context.TODO(), resourceType, tenantID, repo.Conditions{repo.NewEqualCondition("id", appID)}, repo.NoOrderBy, nil) 247 require.EqualError(t, err, apperrors.NewInternalError("item cannot be nil").Error()) 248 }) 249 } 250 251 func TestGetSingleForUpdate(t *testing.T) { 252 sut := repo.NewSingleGetter(appTableName, appColumns) 253 resourceType := resource.Application 254 m2mTable, ok := resourceType.TenantAccessTable() 255 require.True(t, ok) 256 257 t.Run("success", func(t *testing.T) { 258 // GIVEN 259 db, mock := testdb.MockDatabase(t) 260 ctx := persistence.SaveToContext(context.TODO(), db) 261 defer mock.AssertExpectations(t) 262 263 expectedQuery := regexp.QuoteMeta(fmt.Sprintf("SELECT id, name, description FROM %s WHERE id = $1 AND %s FOR UPDATE", appTableName, fmt.Sprintf(tenantIsolationConditionWithoutOwnerCheckFmt, m2mTable, "$2"))) 264 rows := sqlmock.NewRows([]string{"id", "name", "description"}).AddRow(appID, appName, appDescription) 265 mock.ExpectQuery(expectedQuery).WithArgs(appID, tenantID).WillReturnRows(rows) 266 dest := App{} 267 // WHEN 268 err := sut.GetForUpdate(ctx, resourceType, tenantID, repo.Conditions{repo.NewEqualCondition("id", appID)}, repo.NoOrderBy, &dest) 269 // THEN 270 require.NoError(t, err) 271 assert.Equal(t, appID, dest.ID) 272 assert.Equal(t, appName, dest.Name) 273 assert.Equal(t, appDescription, dest.Description) 274 }) 275 } 276 277 func TestGetSingleWithEmbeddedTenant(t *testing.T) { 278 givenID := "id" 279 sut := repo.NewSingleGetterWithEmbeddedTenant(userTableName, "tenant_id", []string{"id", "tenant_id", "first_name", "last_name", "age"}) 280 281 t.Run("success", func(t *testing.T) { 282 // GIVEN 283 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE tenant_id = $1 AND id = $2") 284 db, mock := testdb.MockDatabase(t) 285 ctx := persistence.SaveToContext(context.TODO(), db) 286 defer mock.AssertExpectations(t) 287 rows := sqlmock.NewRows([]string{"id", "first_name", "last_name", "age"}).AddRow(givenID, "givenFirstName", "givenLastName", 18) 288 mock.ExpectQuery(expectedQuery).WithArgs(tenantID, givenID).WillReturnRows(rows) 289 dest := User{} 290 // WHEN 291 err := sut.Get(ctx, UserType, tenantID, repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, &dest) 292 // THEN 293 require.NoError(t, err) 294 assert.Equal(t, givenID, dest.ID) 295 assert.Equal(t, "givenFirstName", dest.FirstName) 296 assert.Equal(t, "givenLastName", dest.LastName) 297 assert.Equal(t, 18, dest.Age) 298 }) 299 300 t.Run("success when no conditions", func(t *testing.T) { 301 // GIVEN 302 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE tenant_id = $1") 303 db, mock := testdb.MockDatabase(t) 304 ctx := persistence.SaveToContext(context.TODO(), db) 305 defer mock.AssertExpectations(t) 306 rows := sqlmock.NewRows([]string{"id", "first_name", "last_name", "age"}).AddRow(givenID, "givenFirstName", "givenLastName", 18) 307 mock.ExpectQuery(expectedQuery).WithArgs(tenantID).WillReturnRows(rows) 308 dest := User{} 309 // WHEN 310 err := sut.Get(ctx, UserType, tenantID, nil, repo.NoOrderBy, &dest) 311 // THEN 312 require.NoError(t, err) 313 assert.Equal(t, givenID, dest.ID) 314 assert.Equal(t, "givenFirstName", dest.FirstName) 315 assert.Equal(t, "givenLastName", dest.LastName) 316 assert.Equal(t, 18, dest.Age) 317 }) 318 319 t.Run("success when more conditions", func(t *testing.T) { 320 // GIVEN 321 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE tenant_id = $1 AND first_name = $2 AND last_name = $3") 322 db, mock := testdb.MockDatabase(t) 323 ctx := persistence.SaveToContext(context.TODO(), db) 324 defer mock.AssertExpectations(t) 325 rows := sqlmock.NewRows([]string{"id"}).AddRow(givenID) 326 mock.ExpectQuery(expectedQuery).WithArgs(tenantID, "john", "doe").WillReturnRows(rows) 327 // WHEN 328 dest := User{} 329 err := sut.Get(ctx, UserType, tenantID, repo.Conditions{repo.NewEqualCondition("first_name", "john"), repo.NewEqualCondition("last_name", "doe")}, repo.NoOrderBy, &dest) 330 // THEN 331 require.NoError(t, err) 332 }) 333 334 t.Run("success with order by params", func(t *testing.T) { 335 // GIVEN 336 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE tenant_id = $1 ORDER BY first_name ASC") 337 db, mock := testdb.MockDatabase(t) 338 ctx := persistence.SaveToContext(context.TODO(), db) 339 defer mock.AssertExpectations(t) 340 rows := sqlmock.NewRows([]string{"id"}).AddRow(givenID) 341 mock.ExpectQuery(expectedQuery).WithArgs(tenantID).WillReturnRows(rows) 342 // WHEN 343 dest := User{} 344 err := sut.Get(ctx, UserType, tenantID, nil, repo.OrderByParams{repo.NewAscOrderBy("first_name")}, &dest) 345 // THEN 346 require.NoError(t, err) 347 }) 348 349 t.Run("success with multiple order by params", func(t *testing.T) { 350 // GIVEN 351 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE tenant_id = $1 ORDER BY first_name ASC, last_name DESC") 352 db, mock := testdb.MockDatabase(t) 353 ctx := persistence.SaveToContext(context.TODO(), db) 354 defer mock.AssertExpectations(t) 355 rows := sqlmock.NewRows([]string{"id"}).AddRow(givenID) 356 mock.ExpectQuery(expectedQuery).WithArgs(tenantID).WillReturnRows(rows) 357 // WHEN 358 dest := User{} 359 err := sut.Get(ctx, UserType, tenantID, nil, repo.OrderByParams{repo.NewAscOrderBy("first_name"), repo.NewDescOrderBy("last_name")}, &dest) 360 // THEN 361 require.NoError(t, err) 362 }) 363 364 t.Run("success with conditions and order by params", func(t *testing.T) { 365 // GIVEN 366 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE tenant_id = $1 AND first_name = $2 AND last_name = $3 ORDER BY first_name ASC") 367 db, mock := testdb.MockDatabase(t) 368 ctx := persistence.SaveToContext(context.TODO(), db) 369 defer mock.AssertExpectations(t) 370 rows := sqlmock.NewRows([]string{"id"}).AddRow(givenID) 371 mock.ExpectQuery(expectedQuery).WithArgs(tenantID, "john", "doe").WillReturnRows(rows) 372 // WHEN 373 dest := User{} 374 err := sut.Get(ctx, 375 UserType, 376 tenantID, 377 repo.Conditions{repo.NewEqualCondition("first_name", "john"), repo.NewEqualCondition("last_name", "doe")}, 378 repo.OrderByParams{repo.NewAscOrderBy("first_name")}, 379 &dest) 380 // THEN 381 require.NoError(t, err) 382 }) 383 384 t.Run("returns error when operation on db failed", func(t *testing.T) { 385 // GIVEN 386 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE tenant_id = $1 AND id = $2") 387 db, mock := testdb.MockDatabase(t) 388 ctx := persistence.SaveToContext(context.TODO(), db) 389 defer mock.AssertExpectations(t) 390 mock.ExpectQuery(expectedQuery).WithArgs(tenantID, givenID).WillReturnError(someError()) 391 dest := User{} 392 // WHEN 393 err := sut.Get(ctx, UserType, tenantID, repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, &dest) 394 // THEN 395 require.EqualError(t, err, "Internal Server Error: Unexpected error while executing SQL query") 396 }) 397 398 t.Run("returns ErrorNotFound if object not found", func(t *testing.T) { 399 // GIVEN 400 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE tenant_id = $1 AND id = $2") 401 db, mock := testdb.MockDatabase(t) 402 ctx := persistence.SaveToContext(context.TODO(), db) 403 defer mock.AssertExpectations(t) 404 noRows := sqlmock.NewRows([]string{"id", "first_name", "last_name", "age"}) 405 mock.ExpectQuery(expectedQuery).WithArgs(tenantID, givenID).WillReturnRows(noRows) 406 dest := User{} 407 // WHEN 408 err := sut.Get(ctx, UserType, tenantID, repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, &dest) 409 // THEN 410 require.NotNil(t, err) 411 assert.True(t, apperrors.IsNotFoundError(err)) 412 }) 413 414 t.Run("returns error if missing persistence context", func(t *testing.T) { 415 ctx := context.TODO() 416 err := sut.Get(ctx, UserType, tenantID, repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, &User{}) 417 require.EqualError(t, err, apperrors.NewInternalError("unable to fetch database from context").Error()) 418 }) 419 420 t.Run("returns error if destination is nil", func(t *testing.T) { 421 err := sut.Get(context.TODO(), UserType, tenantID, repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, nil) 422 require.EqualError(t, err, apperrors.NewInternalError("item cannot be nil").Error()) 423 }) 424 } 425 426 func TestGetSingleGlobal(t *testing.T) { 427 givenID := "id" 428 sut := repo.NewSingleGetterGlobal(UserType, "users", []string{"id", "tenant_id", "first_name", "last_name", "age"}) 429 430 t.Run("success", func(t *testing.T) { 431 // GIVEN 432 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE id = $1") 433 db, mock := testdb.MockDatabase(t) 434 ctx := persistence.SaveToContext(context.TODO(), db) 435 defer mock.AssertExpectations(t) 436 rows := sqlmock.NewRows([]string{"id", "first_name", "last_name", "age"}).AddRow(givenID, "givenFirstName", "givenLastName", 18) 437 mock.ExpectQuery(expectedQuery).WithArgs(givenID).WillReturnRows(rows) 438 dest := User{} 439 // WHEN 440 err := sut.GetGlobal(ctx, repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, &dest) 441 // THEN 442 require.NoError(t, err) 443 assert.Equal(t, givenID, dest.ID) 444 assert.Equal(t, "givenFirstName", dest.FirstName) 445 assert.Equal(t, "givenLastName", dest.LastName) 446 assert.Equal(t, 18, dest.Age) 447 }) 448 449 t.Run("success when no conditions", func(t *testing.T) { 450 // GIVEN 451 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users") 452 db, mock := testdb.MockDatabase(t) 453 ctx := persistence.SaveToContext(context.TODO(), db) 454 defer mock.AssertExpectations(t) 455 rows := sqlmock.NewRows([]string{"id", "first_name", "last_name", "age"}).AddRow(givenID, "givenFirstName", "givenLastName", 18) 456 mock.ExpectQuery(expectedQuery).WillReturnRows(rows) 457 dest := User{} 458 // WHEN 459 err := sut.GetGlobal(ctx, nil, repo.NoOrderBy, &dest) 460 // THEN 461 require.NoError(t, err) 462 assert.Equal(t, givenID, dest.ID) 463 assert.Equal(t, "givenFirstName", dest.FirstName) 464 assert.Equal(t, "givenLastName", dest.LastName) 465 assert.Equal(t, 18, dest.Age) 466 }) 467 468 t.Run("success when more conditions", func(t *testing.T) { 469 // GIVEN 470 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE first_name = $1 AND last_name = $2") 471 db, mock := testdb.MockDatabase(t) 472 ctx := persistence.SaveToContext(context.TODO(), db) 473 defer mock.AssertExpectations(t) 474 rows := sqlmock.NewRows([]string{"id"}).AddRow(givenID) 475 mock.ExpectQuery(expectedQuery).WithArgs("john", "doe").WillReturnRows(rows) 476 // WHEN 477 dest := User{} 478 err := sut.GetGlobal(ctx, repo.Conditions{repo.NewEqualCondition("first_name", "john"), repo.NewEqualCondition("last_name", "doe")}, repo.NoOrderBy, &dest) 479 // THEN 480 require.NoError(t, err) 481 }) 482 483 t.Run("success with order by params", func(t *testing.T) { 484 // GIVEN 485 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users ORDER BY first_name ASC") 486 db, mock := testdb.MockDatabase(t) 487 ctx := persistence.SaveToContext(context.TODO(), db) 488 defer mock.AssertExpectations(t) 489 rows := sqlmock.NewRows([]string{"id"}).AddRow(givenID) 490 mock.ExpectQuery(expectedQuery).WillReturnRows(rows) 491 // WHEN 492 dest := User{} 493 err := sut.GetGlobal(ctx, nil, repo.OrderByParams{repo.NewAscOrderBy("first_name")}, &dest) 494 // THEN 495 require.NoError(t, err) 496 }) 497 498 t.Run("success with multiple order by params", func(t *testing.T) { 499 // GIVEN 500 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users ORDER BY first_name ASC, last_name DESC") 501 db, mock := testdb.MockDatabase(t) 502 ctx := persistence.SaveToContext(context.TODO(), db) 503 defer mock.AssertExpectations(t) 504 rows := sqlmock.NewRows([]string{"id"}).AddRow(givenID) 505 mock.ExpectQuery(expectedQuery).WillReturnRows(rows) 506 // WHEN 507 dest := User{} 508 err := sut.GetGlobal(ctx, nil, repo.OrderByParams{repo.NewAscOrderBy("first_name"), repo.NewDescOrderBy("last_name")}, &dest) 509 // THEN 510 require.NoError(t, err) 511 }) 512 513 t.Run("success with conditions and order by params", func(t *testing.T) { 514 // GIVEN 515 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE first_name = $1 AND last_name = $2 ORDER BY first_name ASC") 516 db, mock := testdb.MockDatabase(t) 517 ctx := persistence.SaveToContext(context.TODO(), db) 518 defer mock.AssertExpectations(t) 519 rows := sqlmock.NewRows([]string{"id"}).AddRow(givenID) 520 mock.ExpectQuery(expectedQuery).WithArgs("john", "doe").WillReturnRows(rows) 521 // WHEN 522 dest := User{} 523 err := sut.GetGlobal(ctx, 524 repo.Conditions{repo.NewEqualCondition("first_name", "john"), repo.NewEqualCondition("last_name", "doe")}, 525 repo.OrderByParams{repo.NewAscOrderBy("first_name")}, 526 &dest) 527 // THEN 528 require.NoError(t, err) 529 }) 530 531 t.Run("returns error when operation on db failed", func(t *testing.T) { 532 // GIVEN 533 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE id = $1") 534 db, mock := testdb.MockDatabase(t) 535 ctx := persistence.SaveToContext(context.TODO(), db) 536 defer mock.AssertExpectations(t) 537 mock.ExpectQuery(expectedQuery).WithArgs(givenID).WillReturnError(someError()) 538 dest := User{} 539 // WHEN 540 err := sut.GetGlobal(ctx, repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, &dest) 541 // THEN 542 require.EqualError(t, err, "Internal Server Error: Unexpected error while executing SQL query") 543 }) 544 545 t.Run("returns ErrorNotFound if object not found", func(t *testing.T) { 546 // GIVEN 547 expectedQuery := regexp.QuoteMeta("SELECT id, tenant_id, first_name, last_name, age FROM users WHERE id = $1") 548 db, mock := testdb.MockDatabase(t) 549 ctx := persistence.SaveToContext(context.TODO(), db) 550 defer mock.AssertExpectations(t) 551 noRows := sqlmock.NewRows([]string{"id", "first_name", "last_name", "age"}) 552 mock.ExpectQuery(expectedQuery).WithArgs(givenID).WillReturnRows(noRows) 553 dest := User{} 554 // WHEN 555 err := sut.GetGlobal(ctx, repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, &dest) 556 // THEN 557 require.NotNil(t, err) 558 assert.True(t, apperrors.IsNotFoundError(err)) 559 }) 560 561 t.Run("returns error if missing persistence context", func(t *testing.T) { 562 ctx := context.TODO() 563 err := sut.GetGlobal(ctx, repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, &User{}) 564 require.EqualError(t, err, apperrors.NewInternalError("unable to fetch database from context").Error()) 565 }) 566 567 t.Run("returns error if destination is nil", func(t *testing.T) { 568 err := sut.GetGlobal(context.TODO(), repo.Conditions{repo.NewEqualCondition("id", givenID)}, repo.NoOrderBy, nil) 569 require.EqualError(t, err, apperrors.NewInternalError("item cannot be nil").Error()) 570 }) 571 }