github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/bundle/service_test.go (about) 1 package bundle_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/kyma-incubator/compass/components/director/pkg/resource" 8 9 "github.com/kyma-incubator/compass/components/director/internal/domain/bundle" 10 "github.com/kyma-incubator/compass/components/director/internal/domain/bundle/automock" 11 "github.com/kyma-incubator/compass/components/director/internal/domain/tenant" 12 "github.com/kyma-incubator/compass/components/director/internal/model" 13 "github.com/kyma-incubator/compass/components/director/pkg/pagination" 14 "github.com/pkg/errors" 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/mock" 17 "github.com/stretchr/testify/require" 18 ) 19 20 func TestService_Create(t *testing.T) { 21 // GIVEN 22 testErr := errors.New("Test error") 23 24 id := "foo" 25 applicationID := appID 26 name := "foo" 27 28 modelInput := model.BundleCreateInput{ 29 Name: name, 30 Description: &desc, 31 InstanceAuthRequestInputSchema: fixBasicSchema(), 32 DefaultInstanceAuth: &model.AuthInput{}, 33 Documents: []*model.DocumentInput{ 34 {Title: "foo", Description: "test", FetchRequest: &model.FetchRequestInput{URL: "doc.foo.bar"}}, 35 {Title: "bar", Description: "test"}, 36 }, 37 APIDefinitions: []*model.APIDefinitionInput{ 38 { 39 Name: "foo", 40 }, 41 { 42 Name: "bar", 43 }, 44 }, 45 APISpecs: []*model.SpecInput{ 46 { 47 FetchRequest: &model.FetchRequestInput{URL: "api.foo.bar"}, 48 }, 49 nil, 50 }, 51 EventDefinitions: []*model.EventDefinitionInput{ 52 { 53 Name: "foo", 54 }, 55 { 56 Name: "bar", 57 }, 58 }, 59 EventSpecs: []*model.SpecInput{ 60 { 61 FetchRequest: &model.FetchRequestInput{URL: "eventapi.foo.bar"}, 62 }, 63 nil, 64 }, 65 } 66 67 modelBundleForApp := fixBasicModelBundle(id, name) 68 modelBundleForApp.ApplicationID = &appID 69 70 modelBundleForAppTemplateVersion := fixBasicModelBundle(id, name) 71 modelBundleForAppTemplateVersion.ApplicationTemplateVersionID = &appTemplateVersionID 72 73 ctx := context.TODO() 74 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 75 76 testCases := []struct { 77 Name string 78 RepositoryFn func() *automock.BundleRepository 79 APIServiceFn func() *automock.APIService 80 EventServiceFn func() *automock.EventService 81 DocumentServiceFn func() *automock.DocumentService 82 UIDServiceFn func() *automock.UIDService 83 Input model.BundleCreateInput 84 ResourceType resource.Type 85 ResourceID string 86 ExpectedErr error 87 }{ 88 { 89 Name: "Success for Application", 90 RepositoryFn: func() *automock.BundleRepository { 91 repo := &automock.BundleRepository{} 92 repo.On("Create", ctx, tenantID, modelBundleForApp).Return(nil).Once() 93 return repo 94 }, 95 UIDServiceFn: func() *automock.UIDService { 96 svc := &automock.UIDService{} 97 svc.On("Generate").Return(id) 98 return svc 99 }, 100 APIServiceFn: func() *automock.APIService { 101 svc := &automock.APIService{} 102 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.APIDefinitions[0], modelInput.APISpecs[0]).Return("", nil).Once() 103 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.APIDefinitions[1], modelInput.APISpecs[1]).Return("", nil).Once() 104 return svc 105 }, 106 EventServiceFn: func() *automock.EventService { 107 svc := &automock.EventService{} 108 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.EventDefinitions[0], modelInput.EventSpecs[0]).Return("", nil).Once() 109 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.EventDefinitions[1], modelInput.EventSpecs[1]).Return("", nil).Once() 110 return svc 111 }, 112 DocumentServiceFn: func() *automock.DocumentService { 113 svc := &automock.DocumentService{} 114 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.Documents[0]).Return("", nil).Once() 115 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.Documents[1]).Return("", nil).Once() 116 return svc 117 }, 118 Input: modelInput, 119 ResourceType: resource.Application, 120 ResourceID: applicationID, 121 ExpectedErr: nil, 122 }, 123 { 124 Name: "Success for Application Template Version", 125 RepositoryFn: func() *automock.BundleRepository { 126 repo := &automock.BundleRepository{} 127 repo.On("CreateGlobal", ctx, modelBundleForAppTemplateVersion).Return(nil).Once() 128 return repo 129 }, 130 UIDServiceFn: func() *automock.UIDService { 131 svc := &automock.UIDService{} 132 svc.On("Generate").Return(id) 133 return svc 134 }, 135 APIServiceFn: func() *automock.APIService { 136 svc := &automock.APIService{} 137 svc.On("CreateInBundle", ctx, resource.ApplicationTemplateVersion, appTemplateVersionID, id, *modelInput.APIDefinitions[0], modelInput.APISpecs[0]).Return("", nil).Once() 138 svc.On("CreateInBundle", ctx, resource.ApplicationTemplateVersion, appTemplateVersionID, id, *modelInput.APIDefinitions[1], modelInput.APISpecs[1]).Return("", nil).Once() 139 return svc 140 }, 141 EventServiceFn: func() *automock.EventService { 142 svc := &automock.EventService{} 143 svc.On("CreateInBundle", ctx, resource.ApplicationTemplateVersion, appTemplateVersionID, id, *modelInput.EventDefinitions[0], modelInput.EventSpecs[0]).Return("", nil).Once() 144 svc.On("CreateInBundle", ctx, resource.ApplicationTemplateVersion, appTemplateVersionID, id, *modelInput.EventDefinitions[1], modelInput.EventSpecs[1]).Return("", nil).Once() 145 return svc 146 }, 147 DocumentServiceFn: func() *automock.DocumentService { 148 svc := &automock.DocumentService{} 149 svc.On("CreateInBundle", ctx, resource.ApplicationTemplateVersion, appTemplateVersionID, id, *modelInput.Documents[0]).Return("", nil).Once() 150 svc.On("CreateInBundle", ctx, resource.ApplicationTemplateVersion, appTemplateVersionID, id, *modelInput.Documents[1]).Return("", nil).Once() 151 return svc 152 }, 153 Input: modelInput, 154 ResourceType: resource.ApplicationTemplateVersion, 155 ResourceID: appTemplateVersionID, 156 ExpectedErr: nil, 157 }, 158 { 159 Name: "Error - Bundle creation for App", 160 RepositoryFn: func() *automock.BundleRepository { 161 repo := &automock.BundleRepository{} 162 repo.On("Create", ctx, tenantID, modelBundleForApp).Return(testErr).Once() 163 return repo 164 }, 165 UIDServiceFn: func() *automock.UIDService { 166 svc := &automock.UIDService{} 167 svc.On("Generate").Return(id).Once() 168 return svc 169 }, 170 APIServiceFn: func() *automock.APIService { 171 return &automock.APIService{} 172 }, 173 EventServiceFn: func() *automock.EventService { 174 return &automock.EventService{} 175 }, 176 DocumentServiceFn: func() *automock.DocumentService { 177 return &automock.DocumentService{} 178 }, 179 Input: modelInput, 180 ResourceType: resource.Application, 181 ResourceID: applicationID, 182 ExpectedErr: testErr, 183 }, 184 { 185 Name: "Error - Bundle creation for App Template Version", 186 RepositoryFn: func() *automock.BundleRepository { 187 repo := &automock.BundleRepository{} 188 repo.On("CreateGlobal", ctx, modelBundleForAppTemplateVersion).Return(testErr).Once() 189 return repo 190 }, 191 UIDServiceFn: func() *automock.UIDService { 192 svc := &automock.UIDService{} 193 svc.On("Generate").Return(id).Once() 194 return svc 195 }, 196 APIServiceFn: func() *automock.APIService { 197 return &automock.APIService{} 198 }, 199 EventServiceFn: func() *automock.EventService { 200 return &automock.EventService{} 201 }, 202 DocumentServiceFn: func() *automock.DocumentService { 203 return &automock.DocumentService{} 204 }, 205 Input: modelInput, 206 ResourceType: resource.ApplicationTemplateVersion, 207 ResourceID: appTemplateVersionID, 208 ExpectedErr: nil, 209 }, 210 { 211 Name: "Error - API creation", 212 RepositoryFn: func() *automock.BundleRepository { 213 repo := &automock.BundleRepository{} 214 repo.On("Create", ctx, tenantID, modelBundleForApp).Return(nil).Once() 215 return repo 216 }, 217 UIDServiceFn: func() *automock.UIDService { 218 svc := &automock.UIDService{} 219 svc.On("Generate").Return(id) 220 return svc 221 }, 222 APIServiceFn: func() *automock.APIService { 223 svc := &automock.APIService{} 224 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.APIDefinitions[0], modelInput.APISpecs[0]).Return("", testErr).Once() 225 return svc 226 }, 227 EventServiceFn: func() *automock.EventService { 228 svc := &automock.EventService{} 229 return svc 230 }, 231 DocumentServiceFn: func() *automock.DocumentService { 232 svc := &automock.DocumentService{} 233 return svc 234 }, 235 Input: modelInput, 236 ResourceType: resource.Application, 237 ResourceID: applicationID, 238 ExpectedErr: testErr, 239 }, 240 { 241 Name: "Error - Event creation", 242 RepositoryFn: func() *automock.BundleRepository { 243 repo := &automock.BundleRepository{} 244 repo.On("Create", ctx, tenantID, modelBundleForApp).Return(nil).Once() 245 return repo 246 }, 247 UIDServiceFn: func() *automock.UIDService { 248 svc := &automock.UIDService{} 249 svc.On("Generate").Return(id) 250 return svc 251 }, 252 APIServiceFn: func() *automock.APIService { 253 svc := &automock.APIService{} 254 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.APIDefinitions[0], modelInput.APISpecs[0]).Return("", nil).Once() 255 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.APIDefinitions[1], modelInput.APISpecs[1]).Return("", nil).Once() 256 return svc 257 }, 258 EventServiceFn: func() *automock.EventService { 259 svc := &automock.EventService{} 260 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.EventDefinitions[0], modelInput.EventSpecs[0]).Return("", testErr).Once() 261 return svc 262 }, 263 DocumentServiceFn: func() *automock.DocumentService { 264 repo := &automock.DocumentService{} 265 return repo 266 }, 267 Input: modelInput, 268 ResourceType: resource.Application, 269 ResourceID: applicationID, 270 ExpectedErr: testErr, 271 }, 272 { 273 Name: "Error - Document creation", 274 RepositoryFn: func() *automock.BundleRepository { 275 repo := &automock.BundleRepository{} 276 repo.On("Create", ctx, tenantID, modelBundleForApp).Return(nil).Once() 277 return repo 278 }, 279 UIDServiceFn: func() *automock.UIDService { 280 svc := &automock.UIDService{} 281 svc.On("Generate").Return(id) 282 return svc 283 }, 284 APIServiceFn: func() *automock.APIService { 285 svc := &automock.APIService{} 286 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.APIDefinitions[0], modelInput.APISpecs[0]).Return("", nil).Once() 287 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.APIDefinitions[1], modelInput.APISpecs[1]).Return("", nil).Once() 288 return svc 289 }, 290 EventServiceFn: func() *automock.EventService { 291 svc := &automock.EventService{} 292 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.EventDefinitions[0], modelInput.EventSpecs[0]).Return("", nil).Once() 293 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.EventDefinitions[1], modelInput.EventSpecs[1]).Return("", nil).Once() 294 return svc 295 }, 296 DocumentServiceFn: func() *automock.DocumentService { 297 svc := &automock.DocumentService{} 298 svc.On("CreateInBundle", ctx, resource.Application, appID, id, *modelInput.Documents[0]).Return("", testErr).Once() 299 return svc 300 }, 301 Input: modelInput, 302 ResourceType: resource.Application, 303 ResourceID: applicationID, 304 ExpectedErr: testErr, 305 }, 306 } 307 308 for _, testCase := range testCases { 309 t.Run(testCase.Name, func(t *testing.T) { 310 // GIVEN 311 repo := testCase.RepositoryFn() 312 uidService := testCase.UIDServiceFn() 313 314 apiSvc := testCase.APIServiceFn() 315 eventSvc := testCase.EventServiceFn() 316 documentSvc := testCase.DocumentServiceFn() 317 svc := bundle.NewService(repo, apiSvc, eventSvc, documentSvc, uidService) 318 319 // WHEN 320 result, err := svc.Create(ctx, testCase.ResourceType, testCase.ResourceID, testCase.Input) 321 322 // THEN 323 if testCase.ExpectedErr != nil { 324 require.Error(t, err) 325 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 326 } else { 327 assert.IsType(t, "string", result) 328 } 329 330 mock.AssertExpectationsForObjects(t, repo, apiSvc, eventSvc, documentSvc, uidService) 331 }) 332 } 333 t.Run("Error when tenant not in context", func(t *testing.T) { 334 svc := bundle.NewService(nil, nil, nil, nil, fixUIDService()) 335 // WHEN 336 _, err := svc.Create(context.TODO(), resource.Application, appID, model.BundleCreateInput{}) 337 // THEN 338 require.Error(t, err) 339 assert.Contains(t, err.Error(), "cannot read tenant from context") 340 }) 341 } 342 343 func TestService_Update(t *testing.T) { 344 // GIVEN 345 testErr := errors.New("Test error") 346 347 id := "foo" 348 name := "bar" 349 350 modelInput := model.BundleUpdateInput{ 351 Name: name, 352 Description: &desc, 353 InstanceAuthRequestInputSchema: fixBasicSchema(), 354 DefaultInstanceAuth: &model.AuthInput{}, 355 } 356 357 inputBundleModel := mock.MatchedBy(func(bndl *model.Bundle) bool { 358 return bndl.Name == modelInput.Name 359 }) 360 361 bundleModelForApp := fixBasicModelBundle(id, name) 362 bundleModelForApp.ApplicationID = &appID 363 364 bundleModelForAppTemplateVersion := fixBasicModelBundle(id, name) 365 bundleModelForApp.ApplicationTemplateVersionID = &appTemplateVersionID 366 367 ctx := context.TODO() 368 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 369 370 testCases := []struct { 371 Name string 372 RepositoryFn func() *automock.BundleRepository 373 Input model.BundleUpdateInput 374 InputID string 375 ResourceType resource.Type 376 ExpectedErr error 377 }{ 378 { 379 Name: "Success for App", 380 RepositoryFn: func() *automock.BundleRepository { 381 repo := &automock.BundleRepository{} 382 repo.On("GetByID", ctx, tenantID, id).Return(bundleModelForApp, nil).Once() 383 repo.On("Update", ctx, tenantID, inputBundleModel).Return(nil).Once() 384 return repo 385 }, 386 InputID: "foo", 387 Input: modelInput, 388 ResourceType: resource.Application, 389 ExpectedErr: nil, 390 }, 391 { 392 Name: "Success for App Template Version", 393 RepositoryFn: func() *automock.BundleRepository { 394 repo := &automock.BundleRepository{} 395 repo.On("GetByIDGlobal", ctx, id).Return(bundleModelForAppTemplateVersion, nil).Once() 396 repo.On("UpdateGlobal", ctx, inputBundleModel).Return(nil).Once() 397 return repo 398 }, 399 InputID: "foo", 400 Input: modelInput, 401 ResourceType: resource.ApplicationTemplateVersion, 402 ExpectedErr: nil, 403 }, 404 { 405 Name: "Update Error", 406 RepositoryFn: func() *automock.BundleRepository { 407 repo := &automock.BundleRepository{} 408 repo.On("GetByID", ctx, tenantID, "foo").Return(bundleModelForApp, nil).Once() 409 repo.On("Update", ctx, tenantID, inputBundleModel).Return(testErr).Once() 410 return repo 411 }, 412 InputID: "foo", 413 Input: modelInput, 414 ResourceType: resource.Application, 415 ExpectedErr: testErr, 416 }, 417 { 418 Name: "Update Error for Application Template Version", 419 RepositoryFn: func() *automock.BundleRepository { 420 repo := &automock.BundleRepository{} 421 repo.On("GetByIDGlobal", ctx, "foo").Return(bundleModelForApp, nil).Once() 422 repo.On("UpdateGlobal", ctx, inputBundleModel).Return(testErr).Once() 423 return repo 424 }, 425 InputID: "foo", 426 Input: modelInput, 427 ResourceType: resource.ApplicationTemplateVersion, 428 ExpectedErr: testErr, 429 }, 430 { 431 Name: "Get Error", 432 RepositoryFn: func() *automock.BundleRepository { 433 repo := &automock.BundleRepository{} 434 repo.On("GetByID", ctx, tenantID, "foo").Return(nil, testErr).Once() 435 return repo 436 }, 437 InputID: "foo", 438 Input: modelInput, 439 ResourceType: resource.Application, 440 ExpectedErr: testErr, 441 }, 442 { 443 Name: "Get Error for Application Template Version", 444 RepositoryFn: func() *automock.BundleRepository { 445 repo := &automock.BundleRepository{} 446 repo.On("GetByIDGlobal", ctx, "foo").Return(nil, testErr).Once() 447 return repo 448 }, 449 InputID: "foo", 450 Input: modelInput, 451 ResourceType: resource.ApplicationTemplateVersion, 452 ExpectedErr: testErr, 453 }, 454 } 455 456 for _, testCase := range testCases { 457 t.Run(testCase.Name, func(t *testing.T) { 458 // GIVEN 459 repo := testCase.RepositoryFn() 460 461 svc := bundle.NewService(repo, nil, nil, nil, nil) 462 463 // WHEN 464 err := svc.Update(ctx, testCase.ResourceType, testCase.InputID, testCase.Input) 465 466 // THEN 467 if testCase.ExpectedErr == nil { 468 require.NoError(t, err) 469 } else { 470 require.Error(t, err) 471 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 472 } 473 474 repo.AssertExpectations(t) 475 }) 476 } 477 t.Run("Error when tenant not in context", func(t *testing.T) { 478 svc := bundle.NewService(nil, nil, nil, nil, nil) 479 // WHEN 480 err := svc.Update(context.TODO(), resource.Application, "", model.BundleUpdateInput{}) 481 // THEN 482 require.Error(t, err) 483 assert.Contains(t, err.Error(), "cannot read tenant from context") 484 }) 485 } 486 487 func TestService_Delete(t *testing.T) { 488 // GIVEN 489 testErr := errors.New("Test error") 490 491 id := "foo" 492 493 ctx := context.TODO() 494 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 495 496 testCases := []struct { 497 Name string 498 RepositoryFn func() *automock.BundleRepository 499 Input model.BundleCreateInput 500 InputID string 501 ResourceType resource.Type 502 ExpectedErr error 503 }{ 504 { 505 Name: "Success for Application", 506 RepositoryFn: func() *automock.BundleRepository { 507 repo := &automock.BundleRepository{} 508 repo.On("Delete", ctx, tenantID, id).Return(nil).Once() 509 return repo 510 }, 511 InputID: id, 512 ResourceType: resource.Application, 513 ExpectedErr: nil, 514 }, 515 { 516 Name: "Success for Application Template Version", 517 RepositoryFn: func() *automock.BundleRepository { 518 repo := &automock.BundleRepository{} 519 repo.On("DeleteGlobal", ctx, id).Return(nil).Once() 520 return repo 521 }, 522 InputID: id, 523 ResourceType: resource.ApplicationTemplateVersion, 524 ExpectedErr: nil, 525 }, 526 { 527 Name: "Delete Error for Application", 528 RepositoryFn: func() *automock.BundleRepository { 529 repo := &automock.BundleRepository{} 530 repo.On("Delete", ctx, tenantID, id).Return(testErr).Once() 531 return repo 532 }, 533 InputID: id, 534 ResourceType: resource.Application, 535 ExpectedErr: testErr, 536 }, 537 { 538 Name: "Delete Error for Application Template Version", 539 RepositoryFn: func() *automock.BundleRepository { 540 repo := &automock.BundleRepository{} 541 repo.On("DeleteGlobal", ctx, id).Return(testErr).Once() 542 return repo 543 }, 544 InputID: id, 545 ResourceType: resource.ApplicationTemplateVersion, 546 ExpectedErr: testErr, 547 }, 548 } 549 550 for _, testCase := range testCases { 551 t.Run(testCase.Name, func(t *testing.T) { 552 // GIVEN 553 repo := testCase.RepositoryFn() 554 555 svc := bundle.NewService(repo, nil, nil, nil, nil) 556 557 // WHEN 558 err := svc.Delete(ctx, testCase.ResourceType, testCase.InputID) 559 560 // THEN 561 if testCase.ExpectedErr == nil { 562 require.NoError(t, err) 563 } else { 564 require.Error(t, err) 565 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 566 } 567 568 repo.AssertExpectations(t) 569 }) 570 } 571 t.Run("Error when tenant not in context", func(t *testing.T) { 572 svc := bundle.NewService(nil, nil, nil, nil, nil) 573 // WHEN 574 err := svc.Delete(context.TODO(), resource.Application, "") 575 // THEN 576 require.Error(t, err) 577 assert.Contains(t, err.Error(), "cannot read tenant from context") 578 }) 579 } 580 581 func TestService_Exist(t *testing.T) { 582 // GIVEN 583 testErr := errors.New("Test error") 584 ctx := tenant.SaveToContext(context.TODO(), tenantID, externalTenantID) 585 id := "foo" 586 587 testCases := []struct { 588 Name string 589 RepoFn func() *automock.BundleRepository 590 ExpectedError error 591 ExpectedOutput bool 592 }{ 593 { 594 Name: "Success", 595 RepoFn: func() *automock.BundleRepository { 596 bndlRepo := &automock.BundleRepository{} 597 bndlRepo.On("Exists", ctx, tenantID, id).Return(true, nil).Once() 598 return bndlRepo 599 }, 600 ExpectedOutput: true, 601 }, 602 { 603 Name: "Error when getting Bundle", 604 RepoFn: func() *automock.BundleRepository { 605 bndlRepo := &automock.BundleRepository{} 606 bndlRepo.On("Exists", ctx, tenantID, id).Return(false, testErr).Once() 607 return bndlRepo 608 }, 609 ExpectedError: testErr, 610 ExpectedOutput: false, 611 }, 612 } 613 614 for _, testCase := range testCases { 615 t.Run(testCase.Name, func(t *testing.T) { 616 bndlRepo := testCase.RepoFn() 617 svc := bundle.NewService(bndlRepo, nil, nil, nil, nil) 618 619 // WHEN 620 result, err := svc.Exist(ctx, id) 621 622 // THEN 623 if testCase.ExpectedError != nil { 624 require.Error(t, err) 625 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 626 } else { 627 assert.NoError(t, err) 628 } 629 assert.Equal(t, testCase.ExpectedOutput, result) 630 631 bndlRepo.AssertExpectations(t) 632 }) 633 } 634 635 t.Run("Error when tenant not in context", func(t *testing.T) { 636 svc := bundle.NewService(nil, nil, nil, nil, nil) 637 // WHEN 638 _, err := svc.Exist(context.TODO(), "") 639 // THEN 640 require.Error(t, err) 641 assert.Contains(t, err.Error(), "cannot read tenant from context") 642 }) 643 } 644 645 func TestService_Get(t *testing.T) { 646 // GIVEN 647 testErr := errors.New("Test error") 648 649 id := "foo" 650 name := "foo" 651 desc := "bar" 652 653 bndl := fixBundleModel(name, desc) 654 655 ctx := context.TODO() 656 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 657 658 testCases := []struct { 659 Name string 660 RepositoryFn func() *automock.BundleRepository 661 Input model.BundleCreateInput 662 InputID string 663 ExpectedBundle *model.Bundle 664 ExpectedErrMessage string 665 }{ 666 { 667 Name: "Success", 668 RepositoryFn: func() *automock.BundleRepository { 669 repo := &automock.BundleRepository{} 670 repo.On("GetByID", ctx, tenantID, id).Return(bndl, nil).Once() 671 return repo 672 }, 673 InputID: id, 674 ExpectedBundle: bndl, 675 ExpectedErrMessage: "", 676 }, 677 { 678 Name: "Returns error when Bundle retrieval failed", 679 RepositoryFn: func() *automock.BundleRepository { 680 repo := &automock.BundleRepository{} 681 repo.On("GetByID", ctx, tenantID, id).Return(nil, testErr).Once() 682 return repo 683 }, 684 InputID: id, 685 ExpectedBundle: bndl, 686 ExpectedErrMessage: testErr.Error(), 687 }, 688 } 689 690 for _, testCase := range testCases { 691 t.Run(testCase.Name, func(t *testing.T) { 692 repo := testCase.RepositoryFn() 693 svc := bundle.NewService(repo, nil, nil, nil, nil) 694 695 // WHEN 696 bndl, err := svc.Get(ctx, testCase.InputID) 697 698 // THEN 699 if testCase.ExpectedErrMessage == "" { 700 require.NoError(t, err) 701 assert.Equal(t, testCase.ExpectedBundle, bndl) 702 } else { 703 require.Error(t, err) 704 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 705 } 706 707 repo.AssertExpectations(t) 708 }) 709 } 710 t.Run("Error when tenant not in context", func(t *testing.T) { 711 svc := bundle.NewService(nil, nil, nil, nil, nil) 712 // WHEN 713 _, err := svc.Get(context.TODO(), "") 714 // THEN 715 require.Error(t, err) 716 assert.Contains(t, err.Error(), "cannot read tenant from context") 717 }) 718 } 719 720 func TestService_GetForApplication(t *testing.T) { 721 // GIVEN 722 testErr := errors.New("Test error") 723 724 id := "foo" 725 appID := "bar" 726 name := "foo" 727 desc := "bar" 728 729 bndl := fixBundleModel(name, desc) 730 731 ctx := context.TODO() 732 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 733 734 testCases := []struct { 735 Name string 736 RepositoryFn func() *automock.BundleRepository 737 Input model.BundleCreateInput 738 InputID string 739 ApplicationID string 740 ExpectedBundle *model.Bundle 741 ExpectedErrMessage string 742 }{ 743 { 744 Name: "Success", 745 RepositoryFn: func() *automock.BundleRepository { 746 repo := &automock.BundleRepository{} 747 repo.On("GetForApplication", ctx, tenantID, id, appID).Return(bndl, nil).Once() 748 return repo 749 }, 750 InputID: id, 751 ApplicationID: appID, 752 ExpectedBundle: bndl, 753 ExpectedErrMessage: "", 754 }, 755 { 756 Name: "Returns error when Bundle retrieval failed", 757 RepositoryFn: func() *automock.BundleRepository { 758 repo := &automock.BundleRepository{} 759 repo.On("GetForApplication", ctx, tenantID, id, appID).Return(nil, testErr).Once() 760 return repo 761 }, 762 InputID: id, 763 ApplicationID: appID, 764 ExpectedBundle: nil, 765 ExpectedErrMessage: testErr.Error(), 766 }, 767 } 768 769 for _, testCase := range testCases { 770 t.Run(testCase.Name, func(t *testing.T) { 771 repo := testCase.RepositoryFn() 772 svc := bundle.NewService(repo, nil, nil, nil, nil) 773 774 // WHEN 775 document, err := svc.GetForApplication(ctx, testCase.InputID, testCase.ApplicationID) 776 777 // THEN 778 if testCase.ExpectedErrMessage == "" { 779 require.NoError(t, err) 780 assert.Equal(t, testCase.ExpectedBundle, document) 781 } else { 782 require.Error(t, err) 783 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 784 } 785 786 repo.AssertExpectations(t) 787 }) 788 } 789 t.Run("Error when tenant not in context", func(t *testing.T) { 790 svc := bundle.NewService(nil, nil, nil, nil, nil) 791 // WHEN 792 _, err := svc.GetForApplication(context.TODO(), "", "") 793 // THEN 794 require.Error(t, err) 795 assert.Contains(t, err.Error(), "cannot read tenant from context") 796 }) 797 } 798 799 func TestService_ListByApplicationIDNoPaging(t *testing.T) { 800 // GIVEN 801 testErr := errors.New("Test error") 802 803 name := "foo" 804 desc := "bar" 805 806 bundles := []*model.Bundle{ 807 fixBundleModel(name, desc), 808 fixBundleModel(name, desc), 809 fixBundleModel(name, desc), 810 } 811 812 ctx := context.TODO() 813 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 814 815 testCases := []struct { 816 Name string 817 RepositoryFn func() *automock.BundleRepository 818 ExpectedResult []*model.Bundle 819 ExpectedErrMessage string 820 }{ 821 { 822 Name: "Success", 823 RepositoryFn: func() *automock.BundleRepository { 824 repo := &automock.BundleRepository{} 825 repo.On("ListByResourceIDNoPaging", ctx, tenantID, appID, resource.Application).Return(bundles, nil).Once() 826 return repo 827 }, 828 ExpectedResult: bundles, 829 ExpectedErrMessage: "", 830 }, 831 { 832 Name: "Returns error when Bundle listing failed", 833 RepositoryFn: func() *automock.BundleRepository { 834 repo := &automock.BundleRepository{} 835 repo.On("ListByResourceIDNoPaging", ctx, tenantID, appID, resource.Application).Return(nil, testErr).Once() 836 return repo 837 }, 838 ExpectedResult: nil, 839 ExpectedErrMessage: testErr.Error(), 840 }, 841 } 842 843 for _, testCase := range testCases { 844 t.Run(testCase.Name, func(t *testing.T) { 845 repo := testCase.RepositoryFn() 846 847 svc := bundle.NewService(repo, nil, nil, nil, nil) 848 849 // WHEN 850 docs, err := svc.ListByApplicationIDNoPaging(ctx, appID) 851 852 // THEN 853 if testCase.ExpectedErrMessage == "" { 854 require.NoError(t, err) 855 assert.Equal(t, testCase.ExpectedResult, docs) 856 } else { 857 require.Error(t, err) 858 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 859 } 860 861 repo.AssertExpectations(t) 862 }) 863 } 864 t.Run("Error when tenant not in context", func(t *testing.T) { 865 svc := bundle.NewService(nil, nil, nil, nil, nil) 866 // WHEN 867 _, err := svc.ListByApplicationIDNoPaging(context.TODO(), "") 868 // THEN 869 require.Error(t, err) 870 assert.Contains(t, err.Error(), "cannot read tenant from context") 871 }) 872 } 873 874 func TestService_ListByApplicationTemplateVersionIDNoPaging(t *testing.T) { 875 // GIVEN 876 testErr := errors.New("Test error") 877 878 name := "foo" 879 880 bundles := []*model.Bundle{ 881 fixBundleModel(name, desc), 882 fixBundleModel(name, desc), 883 } 884 885 ctx := context.TODO() 886 887 testCases := []struct { 888 Name string 889 RepositoryFn func() *automock.BundleRepository 890 ExpectedResult []*model.Bundle 891 ExpectedErrMessage string 892 }{ 893 { 894 Name: "Success", 895 RepositoryFn: func() *automock.BundleRepository { 896 repo := &automock.BundleRepository{} 897 repo.On("ListByResourceIDNoPaging", ctx, "", appTemplateVersionID, resource.ApplicationTemplateVersion).Return(bundles, nil).Once() 898 return repo 899 }, 900 ExpectedResult: bundles, 901 ExpectedErrMessage: "", 902 }, 903 { 904 Name: "Returns error when Bundle listing failed", 905 RepositoryFn: func() *automock.BundleRepository { 906 repo := &automock.BundleRepository{} 907 repo.On("ListByResourceIDNoPaging", ctx, "", appTemplateVersionID, resource.ApplicationTemplateVersion).Return(nil, testErr).Once() 908 return repo 909 }, 910 ExpectedResult: nil, 911 ExpectedErrMessage: testErr.Error(), 912 }, 913 } 914 915 for _, testCase := range testCases { 916 t.Run(testCase.Name, func(t *testing.T) { 917 repo := testCase.RepositoryFn() 918 919 svc := bundle.NewService(repo, nil, nil, nil, nil) 920 921 // WHEN 922 docs, err := svc.ListByApplicationTemplateVersionIDNoPaging(ctx, appTemplateVersionID) 923 924 // THEN 925 if testCase.ExpectedErrMessage == "" { 926 require.NoError(t, err) 927 assert.Equal(t, testCase.ExpectedResult, docs) 928 } else { 929 require.Error(t, err) 930 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 931 } 932 933 repo.AssertExpectations(t) 934 }) 935 } 936 t.Run("Error when tenant not in context", func(t *testing.T) { 937 svc := bundle.NewService(nil, nil, nil, nil, nil) 938 // WHEN 939 _, err := svc.ListByApplicationIDNoPaging(context.TODO(), "") 940 // THEN 941 require.Error(t, err) 942 assert.Contains(t, err.Error(), "cannot read tenant from context") 943 }) 944 } 945 946 func TestService_ListByApplicationIDs(t *testing.T) { 947 // GIVEN 948 testErr := errors.New("Test error") 949 950 firstAppID := "bar" 951 secondAppID := "bar2" 952 name := "foo" 953 desc := "bar" 954 appIDs := []string{firstAppID, secondAppID} 955 956 bundleFirstApp := fixBundleModel(name, desc) 957 bundleFirstApp.ApplicationID = &firstAppID 958 bundleSecondApp := fixBundleModel(name, desc) 959 bundleSecondApp.ApplicationID = &secondAppID 960 961 bundlesFirstApp := []*model.Bundle{bundleFirstApp} 962 bundlesSecondApp := []*model.Bundle{bundleSecondApp} 963 964 bundlePageFirstApp := &model.BundlePage{ 965 Data: bundlesFirstApp, 966 TotalCount: len(bundlesFirstApp), 967 PageInfo: &pagination.Page{ 968 HasNextPage: false, 969 EndCursor: "end", 970 StartCursor: "start", 971 }, 972 } 973 bundlePageSecondApp := &model.BundlePage{ 974 Data: bundlesSecondApp, 975 TotalCount: len(bundlesSecondApp), 976 PageInfo: &pagination.Page{ 977 HasNextPage: false, 978 EndCursor: "end", 979 StartCursor: "start", 980 }, 981 } 982 983 bundlePages := []*model.BundlePage{bundlePageFirstApp, bundlePageSecondApp} 984 985 after := "test" 986 987 ctx := context.TODO() 988 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 989 990 testCases := []struct { 991 Name string 992 PageSize int 993 RepositoryFn func() *automock.BundleRepository 994 ExpectedResult []*model.BundlePage 995 ExpectedErrMessage string 996 }{ 997 { 998 Name: "Success", 999 RepositoryFn: func() *automock.BundleRepository { 1000 repo := &automock.BundleRepository{} 1001 repo.On("ListByApplicationIDs", ctx, tenantID, appIDs, 2, after).Return(bundlePages, nil).Once() 1002 return repo 1003 }, 1004 PageSize: 2, 1005 ExpectedResult: bundlePages, 1006 ExpectedErrMessage: "", 1007 }, 1008 { 1009 Name: "Return error when page size is less than 1", 1010 RepositoryFn: func() *automock.BundleRepository { 1011 repo := &automock.BundleRepository{} 1012 return repo 1013 }, 1014 PageSize: 0, 1015 ExpectedResult: bundlePages, 1016 ExpectedErrMessage: "page size must be between 1 and 200", 1017 }, 1018 { 1019 Name: "Return error when page size is bigger than 200", 1020 RepositoryFn: func() *automock.BundleRepository { 1021 repo := &automock.BundleRepository{} 1022 return repo 1023 }, 1024 PageSize: 201, 1025 ExpectedResult: bundlePages, 1026 ExpectedErrMessage: "page size must be between 1 and 200", 1027 }, 1028 { 1029 Name: "Returns error when Bundle listing failed", 1030 RepositoryFn: func() *automock.BundleRepository { 1031 repo := &automock.BundleRepository{} 1032 repo.On("ListByApplicationIDs", ctx, tenantID, appIDs, 2, after).Return(nil, testErr).Once() 1033 return repo 1034 }, 1035 PageSize: 2, 1036 ExpectedResult: nil, 1037 ExpectedErrMessage: testErr.Error(), 1038 }, 1039 } 1040 1041 for _, testCase := range testCases { 1042 t.Run(testCase.Name, func(t *testing.T) { 1043 repo := testCase.RepositoryFn() 1044 1045 svc := bundle.NewService(repo, nil, nil, nil, nil) 1046 1047 // WHEN 1048 bndls, err := svc.ListByApplicationIDs(ctx, appIDs, testCase.PageSize, after) 1049 1050 // then 1051 if testCase.ExpectedErrMessage == "" { 1052 require.NoError(t, err) 1053 assert.Equal(t, testCase.ExpectedResult, bndls) 1054 } else { 1055 require.Error(t, err) 1056 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 1057 } 1058 1059 repo.AssertExpectations(t) 1060 }) 1061 } 1062 t.Run("Error when tenant not in context", func(t *testing.T) { 1063 svc := bundle.NewService(nil, nil, nil, nil, nil) 1064 // WHEN 1065 _, err := svc.ListByApplicationIDs(context.TODO(), nil, 5, "") 1066 // THEN 1067 require.Error(t, err) 1068 assert.Contains(t, err.Error(), "cannot read tenant from context") 1069 }) 1070 } 1071 1072 func fixUIDService() *automock.UIDService { 1073 svc := &automock.UIDService{} 1074 svc.On("Generate").Return(appID) 1075 return svc 1076 }