github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/product/service_test.go (about) 1 package product_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/product" 10 "github.com/kyma-incubator/compass/components/director/internal/domain/product/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/pkg/errors" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/mock" 16 "github.com/stretchr/testify/require" 17 ) 18 19 func TestService_Create(t *testing.T) { 20 // GIVEN 21 testErr := errors.New("Test error") 22 23 ctx := context.TODO() 24 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 25 26 modelProductForApp := fixProductModelForApp() 27 modelProductForAppTemplateVersion := fixProductModelForAppTemplateVersion() 28 modelInput := *fixProductModelInput() 29 30 testCases := []struct { 31 Name string 32 RepositoryFn func() *automock.ProductRepository 33 UIDServiceFn func() *automock.UIDService 34 Input model.ProductInput 35 ResourceType resource.Type 36 ResourceID string 37 ExpectedErr error 38 }{ 39 { 40 Name: "Success for Application", 41 RepositoryFn: func() *automock.ProductRepository { 42 repo := &automock.ProductRepository{} 43 repo.On("Create", ctx, tenantID, modelProductForApp).Return(nil).Once() 44 return repo 45 }, 46 UIDServiceFn: func() *automock.UIDService { 47 svc := &automock.UIDService{} 48 svc.On("Generate").Return(productID) 49 return svc 50 }, 51 Input: modelInput, 52 ResourceType: resource.Application, 53 ResourceID: appID, 54 ExpectedErr: nil, 55 }, 56 { 57 Name: "Success for Application Template Version", 58 RepositoryFn: func() *automock.ProductRepository { 59 repo := &automock.ProductRepository{} 60 repo.On("CreateGlobal", ctx, modelProductForAppTemplateVersion).Return(nil).Once() 61 return repo 62 }, 63 UIDServiceFn: func() *automock.UIDService { 64 svc := &automock.UIDService{} 65 svc.On("Generate").Return(productID) 66 return svc 67 }, 68 Input: modelInput, 69 ResourceType: resource.ApplicationTemplateVersion, 70 ResourceID: appTemplateVersionID, 71 ExpectedErr: nil, 72 }, 73 { 74 Name: "Error - Product creation for Application", 75 RepositoryFn: func() *automock.ProductRepository { 76 repo := &automock.ProductRepository{} 77 repo.On("Create", ctx, tenantID, modelProductForApp).Return(testErr).Once() 78 return repo 79 }, 80 UIDServiceFn: func() *automock.UIDService { 81 svc := &automock.UIDService{} 82 svc.On("Generate").Return(productID) 83 return svc 84 }, 85 Input: modelInput, 86 ResourceType: resource.Application, 87 ResourceID: appID, 88 ExpectedErr: testErr, 89 }, 90 { 91 Name: "Error - Product creation for Application Template Version", 92 RepositoryFn: func() *automock.ProductRepository { 93 repo := &automock.ProductRepository{} 94 repo.On("CreateGlobal", ctx, modelProductForAppTemplateVersion).Return(testErr).Once() 95 return repo 96 }, 97 UIDServiceFn: func() *automock.UIDService { 98 svc := &automock.UIDService{} 99 svc.On("Generate").Return(productID) 100 return svc 101 }, 102 Input: modelInput, 103 ResourceType: resource.ApplicationTemplateVersion, 104 ResourceID: appTemplateVersionID, 105 ExpectedErr: testErr, 106 }, 107 } 108 109 for _, testCase := range testCases { 110 t.Run(testCase.Name, func(t *testing.T) { 111 // GIVEN 112 repo := testCase.RepositoryFn() 113 uidSvc := testCase.UIDServiceFn() 114 115 svc := product.NewService(repo, uidSvc) 116 117 // WHEN 118 result, err := svc.Create(ctx, testCase.ResourceType, testCase.ResourceID, testCase.Input) 119 120 // then 121 if testCase.ExpectedErr != nil { 122 require.Error(t, err) 123 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 124 } else { 125 assert.IsType(t, "string", result) 126 } 127 128 mock.AssertExpectationsForObjects(t, repo) 129 }) 130 } 131 t.Run("Error when tenant not in context", func(t *testing.T) { 132 svc := product.NewService(nil, fixUIDService()) 133 // WHEN 134 _, err := svc.Create(context.TODO(), resource.Application, "", model.ProductInput{}) 135 // THEN 136 require.Error(t, err) 137 assert.Contains(t, err.Error(), "cannot read tenant from context") 138 }) 139 } 140 141 func TestService_CreateGlobal(t *testing.T) { 142 // GIVEN 143 testErr := errors.New("Test error") 144 145 ctx := context.TODO() 146 147 modelProduct := fixGlobalProductModel() 148 modelInput := *fixProductModelInput() 149 150 testCases := []struct { 151 Name string 152 RepositoryFn func() *automock.ProductRepository 153 UIDServiceFn func() *automock.UIDService 154 Input model.ProductInput 155 ExpectedErr error 156 }{ 157 { 158 Name: "Success", 159 RepositoryFn: func() *automock.ProductRepository { 160 repo := &automock.ProductRepository{} 161 repo.On("CreateGlobal", ctx, modelProduct).Return(nil).Once() 162 return repo 163 }, 164 UIDServiceFn: func() *automock.UIDService { 165 svc := &automock.UIDService{} 166 svc.On("Generate").Return(productID) 167 return svc 168 }, 169 Input: modelInput, 170 ExpectedErr: nil, 171 }, 172 { 173 Name: "Error - Product creation", 174 RepositoryFn: func() *automock.ProductRepository { 175 repo := &automock.ProductRepository{} 176 repo.On("CreateGlobal", ctx, modelProduct).Return(testErr).Once() 177 return repo 178 }, 179 UIDServiceFn: func() *automock.UIDService { 180 svc := &automock.UIDService{} 181 svc.On("Generate").Return(productID) 182 return svc 183 }, 184 Input: modelInput, 185 ExpectedErr: testErr, 186 }, 187 } 188 189 for _, testCase := range testCases { 190 t.Run(testCase.Name, func(t *testing.T) { 191 // GIVEN 192 repo := testCase.RepositoryFn() 193 uidSvc := testCase.UIDServiceFn() 194 195 svc := product.NewService(repo, uidSvc) 196 197 // WHEN 198 result, err := svc.CreateGlobal(ctx, testCase.Input) 199 200 // then 201 if testCase.ExpectedErr != nil { 202 require.Error(t, err) 203 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 204 } else { 205 assert.IsType(t, "string", result) 206 } 207 208 mock.AssertExpectationsForObjects(t, repo) 209 }) 210 } 211 } 212 213 func TestService_Update(t *testing.T) { 214 // GIVEN 215 testErr := errors.New("Test error") 216 217 modelProductForApp := fixProductModelForApp() 218 modelProductForAppTemplateVersion := fixProductModelForApp() 219 modelInput := *fixProductModelInput() 220 221 inputProductModel := mock.MatchedBy(func(prod *model.Product) bool { 222 return prod.Title == modelInput.Title 223 }) 224 225 ctx := context.TODO() 226 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 227 228 testCases := []struct { 229 Name string 230 RepositoryFn func() *automock.ProductRepository 231 Input model.ProductInput 232 InputID string 233 ResourceType resource.Type 234 ExpectedErr error 235 }{ 236 { 237 Name: "Success for Application", 238 RepositoryFn: func() *automock.ProductRepository { 239 repo := &automock.ProductRepository{} 240 repo.On("GetByID", ctx, tenantID, productID).Return(modelProductForApp, nil).Once() 241 repo.On("Update", ctx, tenantID, inputProductModel).Return(nil).Once() 242 return repo 243 }, 244 InputID: productID, 245 Input: modelInput, 246 ResourceType: resource.Application, 247 ExpectedErr: nil, 248 }, 249 { 250 Name: "Success for Application Template Version", 251 RepositoryFn: func() *automock.ProductRepository { 252 repo := &automock.ProductRepository{} 253 repo.On("GetByIDGlobal", ctx, productID).Return(modelProductForAppTemplateVersion, nil).Once() 254 repo.On("UpdateGlobal", ctx, inputProductModel).Return(nil).Once() 255 return repo 256 }, 257 InputID: productID, 258 Input: modelInput, 259 ResourceType: resource.ApplicationTemplateVersion, 260 ExpectedErr: nil, 261 }, 262 { 263 Name: "Update Error for Application", 264 RepositoryFn: func() *automock.ProductRepository { 265 repo := &automock.ProductRepository{} 266 repo.On("GetByID", ctx, tenantID, productID).Return(modelProductForApp, nil).Once() 267 repo.On("Update", ctx, tenantID, inputProductModel).Return(testErr).Once() 268 return repo 269 }, 270 InputID: productID, 271 Input: modelInput, 272 ResourceType: resource.Application, 273 ExpectedErr: testErr, 274 }, 275 { 276 Name: "Update Error for Application Template Version", 277 RepositoryFn: func() *automock.ProductRepository { 278 repo := &automock.ProductRepository{} 279 repo.On("GetByIDGlobal", ctx, productID).Return(modelProductForAppTemplateVersion, nil).Once() 280 repo.On("UpdateGlobal", ctx, inputProductModel).Return(testErr).Once() 281 return repo 282 }, 283 InputID: productID, 284 Input: modelInput, 285 ResourceType: resource.ApplicationTemplateVersion, 286 ExpectedErr: testErr, 287 }, 288 { 289 Name: "Get Error for Application", 290 RepositoryFn: func() *automock.ProductRepository { 291 repo := &automock.ProductRepository{} 292 repo.On("GetByID", ctx, tenantID, productID).Return(nil, testErr).Once() 293 return repo 294 }, 295 InputID: productID, 296 Input: modelInput, 297 ResourceType: resource.Application, 298 ExpectedErr: testErr, 299 }, 300 { 301 Name: "Get Error for Application Template Version", 302 RepositoryFn: func() *automock.ProductRepository { 303 repo := &automock.ProductRepository{} 304 repo.On("GetByIDGlobal", ctx, productID).Return(nil, testErr).Once() 305 return repo 306 }, 307 InputID: productID, 308 Input: modelInput, 309 ResourceType: resource.ApplicationTemplateVersion, 310 ExpectedErr: testErr, 311 }, 312 } 313 314 for _, testCase := range testCases { 315 t.Run(testCase.Name, func(t *testing.T) { 316 // GIVEN 317 repo := testCase.RepositoryFn() 318 319 svc := product.NewService(repo, nil) 320 321 // WHEN 322 err := svc.Update(ctx, testCase.ResourceType, testCase.InputID, testCase.Input) 323 324 // then 325 if testCase.ExpectedErr == nil { 326 require.NoError(t, err) 327 } else { 328 require.Error(t, err) 329 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 330 } 331 332 repo.AssertExpectations(t) 333 }) 334 } 335 t.Run("Error when tenant not in context", func(t *testing.T) { 336 svc := product.NewService(nil, nil) 337 // WHEN 338 err := svc.Update(context.TODO(), resource.Application, "", model.ProductInput{}) 339 // THEN 340 require.Error(t, err) 341 assert.Contains(t, err.Error(), "cannot read tenant from context") 342 }) 343 } 344 345 func TestService_UpdateGlobal(t *testing.T) { 346 // GIVEN 347 testErr := errors.New("Test error") 348 349 modelProduct := fixGlobalProductModel() 350 modelInput := *fixProductModelInput() 351 352 inputProductModel := mock.MatchedBy(func(prod *model.Product) bool { 353 return prod.Title == modelInput.Title 354 }) 355 356 ctx := context.TODO() 357 358 testCases := []struct { 359 Name string 360 RepositoryFn func() *automock.ProductRepository 361 Input model.ProductInput 362 InputID string 363 ExpectedErr error 364 }{ 365 { 366 Name: "Success", 367 RepositoryFn: func() *automock.ProductRepository { 368 repo := &automock.ProductRepository{} 369 repo.On("GetByIDGlobal", ctx, productID).Return(modelProduct, nil).Once() 370 repo.On("UpdateGlobal", ctx, inputProductModel).Return(nil).Once() 371 return repo 372 }, 373 InputID: productID, 374 Input: modelInput, 375 ExpectedErr: nil, 376 }, 377 { 378 Name: "UpdateGlobal Error", 379 RepositoryFn: func() *automock.ProductRepository { 380 repo := &automock.ProductRepository{} 381 repo.On("GetByIDGlobal", ctx, productID).Return(modelProduct, nil).Once() 382 repo.On("UpdateGlobal", ctx, inputProductModel).Return(testErr).Once() 383 return repo 384 }, 385 InputID: productID, 386 Input: modelInput, 387 ExpectedErr: testErr, 388 }, 389 { 390 Name: "Get Error", 391 RepositoryFn: func() *automock.ProductRepository { 392 repo := &automock.ProductRepository{} 393 repo.On("GetByIDGlobal", ctx, productID).Return(nil, testErr).Once() 394 return repo 395 }, 396 InputID: productID, 397 Input: modelInput, 398 ExpectedErr: testErr, 399 }, 400 } 401 402 for _, testCase := range testCases { 403 t.Run(testCase.Name, func(t *testing.T) { 404 // GIVEN 405 repo := testCase.RepositoryFn() 406 407 svc := product.NewService(repo, nil) 408 409 // WHEN 410 err := svc.UpdateGlobal(ctx, testCase.InputID, testCase.Input) 411 412 // then 413 if testCase.ExpectedErr == nil { 414 require.NoError(t, err) 415 } else { 416 require.Error(t, err) 417 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 418 } 419 420 repo.AssertExpectations(t) 421 }) 422 } 423 } 424 425 func TestService_Delete(t *testing.T) { 426 // GIVEN 427 testErr := errors.New("Test error") 428 429 ctx := context.TODO() 430 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 431 432 testCases := []struct { 433 Name string 434 RepositoryFn func() *automock.ProductRepository 435 Input model.ProductInput 436 InputID string 437 ResourceType resource.Type 438 ExpectedErr error 439 }{ 440 { 441 Name: "Success for Application", 442 RepositoryFn: func() *automock.ProductRepository { 443 repo := &automock.ProductRepository{} 444 repo.On("Delete", ctx, tenantID, productID).Return(nil).Once() 445 return repo 446 }, 447 InputID: productID, 448 ResourceType: resource.Application, 449 ExpectedErr: nil, 450 }, 451 { 452 Name: "Success for Application Template Version", 453 RepositoryFn: func() *automock.ProductRepository { 454 repo := &automock.ProductRepository{} 455 repo.On("DeleteGlobal", ctx, productID).Return(nil).Once() 456 return repo 457 }, 458 InputID: productID, 459 ResourceType: resource.ApplicationTemplateVersion, 460 ExpectedErr: nil, 461 }, 462 { 463 Name: "Delete Error for Application", 464 RepositoryFn: func() *automock.ProductRepository { 465 repo := &automock.ProductRepository{} 466 repo.On("Delete", ctx, tenantID, productID).Return(testErr).Once() 467 return repo 468 }, 469 InputID: productID, 470 ResourceType: resource.Application, 471 ExpectedErr: testErr, 472 }, 473 { 474 Name: "Delete Error for Application Template Version", 475 RepositoryFn: func() *automock.ProductRepository { 476 repo := &automock.ProductRepository{} 477 repo.On("DeleteGlobal", ctx, productID).Return(testErr).Once() 478 return repo 479 }, 480 InputID: productID, 481 ResourceType: resource.ApplicationTemplateVersion, 482 ExpectedErr: testErr, 483 }, 484 } 485 486 for _, testCase := range testCases { 487 t.Run(testCase.Name, func(t *testing.T) { 488 // GIVEN 489 repo := testCase.RepositoryFn() 490 491 svc := product.NewService(repo, nil) 492 493 // WHEN 494 err := svc.Delete(ctx, testCase.ResourceType, testCase.InputID) 495 496 // then 497 if testCase.ExpectedErr == nil { 498 require.NoError(t, err) 499 } else { 500 require.Error(t, err) 501 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 502 } 503 504 repo.AssertExpectations(t) 505 }) 506 } 507 t.Run("Error when tenant not in context", func(t *testing.T) { 508 svc := product.NewService(nil, nil) 509 // WHEN 510 err := svc.Delete(context.TODO(), resource.Application, "") 511 // THEN 512 require.Error(t, err) 513 assert.Contains(t, err.Error(), "cannot read tenant from context") 514 }) 515 } 516 517 func TestService_DeleteGlobal(t *testing.T) { 518 // GIVEN 519 testErr := errors.New("Test error") 520 521 ctx := context.TODO() 522 523 testCases := []struct { 524 Name string 525 RepositoryFn func() *automock.ProductRepository 526 Input model.ProductInput 527 InputID string 528 ExpectedErr error 529 }{ 530 { 531 Name: "Success", 532 RepositoryFn: func() *automock.ProductRepository { 533 repo := &automock.ProductRepository{} 534 repo.On("DeleteGlobal", ctx, productID).Return(nil).Once() 535 return repo 536 }, 537 InputID: productID, 538 ExpectedErr: nil, 539 }, 540 { 541 Name: "DeleteGlobal Error", 542 RepositoryFn: func() *automock.ProductRepository { 543 repo := &automock.ProductRepository{} 544 repo.On("DeleteGlobal", ctx, productID).Return(testErr).Once() 545 return repo 546 }, 547 InputID: productID, 548 ExpectedErr: testErr, 549 }, 550 } 551 552 for _, testCase := range testCases { 553 t.Run(testCase.Name, func(t *testing.T) { 554 // GIVEN 555 repo := testCase.RepositoryFn() 556 557 svc := product.NewService(repo, nil) 558 559 // WHEN 560 err := svc.DeleteGlobal(ctx, testCase.InputID) 561 562 // then 563 if testCase.ExpectedErr == nil { 564 require.NoError(t, err) 565 } else { 566 require.Error(t, err) 567 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 568 } 569 570 repo.AssertExpectations(t) 571 }) 572 } 573 } 574 575 func TestService_Exist(t *testing.T) { 576 // GIVEN 577 testErr := errors.New("Test error") 578 ctx := tenant.SaveToContext(context.TODO(), tenantID, externalTenantID) 579 580 testCases := []struct { 581 Name string 582 RepoFn func() *automock.ProductRepository 583 ExpectedError error 584 ExpectedOutput bool 585 }{ 586 { 587 Name: "Success", 588 RepoFn: func() *automock.ProductRepository { 589 productRepo := &automock.ProductRepository{} 590 productRepo.On("Exists", ctx, tenantID, productID).Return(true, nil).Once() 591 return productRepo 592 }, 593 ExpectedOutput: true, 594 }, 595 { 596 Name: "Error when getting Product", 597 RepoFn: func() *automock.ProductRepository { 598 productRepo := &automock.ProductRepository{} 599 productRepo.On("Exists", ctx, tenantID, productID).Return(false, testErr).Once() 600 return productRepo 601 }, 602 ExpectedError: testErr, 603 ExpectedOutput: false, 604 }, 605 } 606 607 for _, testCase := range testCases { 608 t.Run(testCase.Name, func(t *testing.T) { 609 productRepo := testCase.RepoFn() 610 svc := product.NewService(productRepo, nil) 611 612 // WHEN 613 result, err := svc.Exist(ctx, productID) 614 615 // THEN 616 if testCase.ExpectedError != nil { 617 require.Error(t, err) 618 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 619 } else { 620 assert.NoError(t, err) 621 } 622 assert.Equal(t, testCase.ExpectedOutput, result) 623 624 productRepo.AssertExpectations(t) 625 }) 626 } 627 628 t.Run("Error when tenant not in context", func(t *testing.T) { 629 svc := product.NewService(nil, nil) 630 // WHEN 631 _, err := svc.Exist(context.TODO(), "") 632 // THEN 633 require.Error(t, err) 634 assert.Contains(t, err.Error(), "cannot read tenant from context") 635 }) 636 } 637 638 func TestService_Get(t *testing.T) { 639 // GIVEN 640 testErr := errors.New("Test error") 641 642 productModel := fixProductModelForApp() 643 644 ctx := context.TODO() 645 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 646 647 testCases := []struct { 648 Name string 649 RepositoryFn func() *automock.ProductRepository 650 Input model.ProductInput 651 InputID string 652 ExpectedProduct *model.Product 653 ExpectedErrMessage string 654 }{ 655 { 656 Name: "Success", 657 RepositoryFn: func() *automock.ProductRepository { 658 repo := &automock.ProductRepository{} 659 repo.On("GetByID", ctx, tenantID, productID).Return(productModel, nil).Once() 660 return repo 661 }, 662 InputID: productID, 663 ExpectedProduct: productModel, 664 ExpectedErrMessage: "", 665 }, 666 { 667 Name: "Returns error when Product retrieval failed", 668 RepositoryFn: func() *automock.ProductRepository { 669 repo := &automock.ProductRepository{} 670 repo.On("GetByID", ctx, tenantID, productID).Return(nil, testErr).Once() 671 return repo 672 }, 673 InputID: productID, 674 ExpectedProduct: productModel, 675 ExpectedErrMessage: testErr.Error(), 676 }, 677 } 678 679 for _, testCase := range testCases { 680 t.Run(testCase.Name, func(t *testing.T) { 681 repo := testCase.RepositoryFn() 682 svc := product.NewService(repo, nil) 683 684 // WHEN 685 prod, err := svc.Get(ctx, testCase.InputID) 686 687 // then 688 if testCase.ExpectedErrMessage == "" { 689 require.NoError(t, err) 690 assert.Equal(t, testCase.ExpectedProduct, prod) 691 } else { 692 require.Error(t, err) 693 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 694 } 695 696 repo.AssertExpectations(t) 697 }) 698 } 699 t.Run("Error when tenant not in context", func(t *testing.T) { 700 svc := product.NewService(nil, nil) 701 // WHEN 702 _, err := svc.Get(context.TODO(), "") 703 // THEN 704 require.Error(t, err) 705 assert.Contains(t, err.Error(), "cannot read tenant from context") 706 }) 707 } 708 709 func TestService_ListByApplicationID(t *testing.T) { 710 // GIVEN 711 testErr := errors.New("Test error") 712 713 products := []*model.Product{ 714 fixProductModelForApp(), 715 fixProductModelForApp(), 716 fixProductModelForApp(), 717 } 718 719 ctx := context.TODO() 720 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 721 722 testCases := []struct { 723 Name string 724 PageSize int 725 RepositoryFn func() *automock.ProductRepository 726 ExpectedResult []*model.Product 727 ExpectedErrMessage string 728 }{ 729 { 730 Name: "Success", 731 RepositoryFn: func() *automock.ProductRepository { 732 repo := &automock.ProductRepository{} 733 repo.On("ListByResourceID", ctx, tenantID, appID, resource.Application).Return(products, nil).Once() 734 return repo 735 }, 736 PageSize: 2, 737 ExpectedResult: products, 738 ExpectedErrMessage: "", 739 }, 740 { 741 Name: "Returns error when APIDefinition listing failed", 742 RepositoryFn: func() *automock.ProductRepository { 743 repo := &automock.ProductRepository{} 744 repo.On("ListByResourceID", ctx, tenantID, appID, resource.Application).Return(nil, testErr).Once() 745 return repo 746 }, 747 PageSize: 2, 748 ExpectedResult: nil, 749 ExpectedErrMessage: testErr.Error(), 750 }, 751 } 752 753 for _, testCase := range testCases { 754 t.Run(testCase.Name, func(t *testing.T) { 755 repo := testCase.RepositoryFn() 756 757 svc := product.NewService(repo, nil) 758 759 // WHEN 760 docs, err := svc.ListByApplicationID(ctx, appID) 761 762 // then 763 if testCase.ExpectedErrMessage == "" { 764 require.NoError(t, err) 765 assert.Equal(t, testCase.ExpectedResult, docs) 766 } else { 767 require.Error(t, err) 768 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 769 } 770 771 repo.AssertExpectations(t) 772 }) 773 } 774 t.Run("Error when tenant not in context", func(t *testing.T) { 775 svc := product.NewService(nil, nil) 776 // WHEN 777 _, err := svc.ListByApplicationID(context.TODO(), "") 778 // THEN 779 require.Error(t, err) 780 assert.Contains(t, err.Error(), "cannot read tenant from context") 781 }) 782 } 783 784 func TestService_ListByApplicationTemplateVersionID(t *testing.T) { 785 // GIVEN 786 testErr := errors.New("Test error") 787 788 products := []*model.Product{ 789 fixProductModelForAppTemplateVersion(), 790 fixProductModelForAppTemplateVersion(), 791 } 792 793 ctx := context.TODO() 794 795 testCases := []struct { 796 Name string 797 PageSize int 798 RepositoryFn func() *automock.ProductRepository 799 ExpectedResult []*model.Product 800 ExpectedErrMessage string 801 }{ 802 { 803 Name: "Success", 804 RepositoryFn: func() *automock.ProductRepository { 805 repo := &automock.ProductRepository{} 806 repo.On("ListByResourceID", ctx, "", appTemplateVersionID, resource.ApplicationTemplateVersion).Return(products, nil).Once() 807 return repo 808 }, 809 PageSize: 2, 810 ExpectedResult: products, 811 ExpectedErrMessage: "", 812 }, 813 { 814 Name: "Returns error when APIDefinition listing failed", 815 RepositoryFn: func() *automock.ProductRepository { 816 repo := &automock.ProductRepository{} 817 repo.On("ListByResourceID", ctx, "", appTemplateVersionID, resource.ApplicationTemplateVersion).Return(nil, testErr).Once() 818 return repo 819 }, 820 PageSize: 2, 821 ExpectedResult: nil, 822 ExpectedErrMessage: testErr.Error(), 823 }, 824 } 825 826 for _, testCase := range testCases { 827 t.Run(testCase.Name, func(t *testing.T) { 828 repo := testCase.RepositoryFn() 829 830 svc := product.NewService(repo, nil) 831 832 // WHEN 833 docs, err := svc.ListByApplicationTemplateVersionID(ctx, appTemplateVersionID) 834 835 // then 836 if testCase.ExpectedErrMessage == "" { 837 require.NoError(t, err) 838 assert.Equal(t, testCase.ExpectedResult, docs) 839 } else { 840 require.Error(t, err) 841 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 842 } 843 844 repo.AssertExpectations(t) 845 }) 846 } 847 t.Run("Error when tenant not in context", func(t *testing.T) { 848 svc := product.NewService(nil, nil) 849 // WHEN 850 _, err := svc.ListByApplicationID(context.TODO(), "") 851 // THEN 852 require.Error(t, err) 853 assert.Contains(t, err.Error(), "cannot read tenant from context") 854 }) 855 } 856 857 func TestService_ListGlobal(t *testing.T) { 858 // GIVEN 859 testErr := errors.New("Test error") 860 861 products := []*model.Product{ 862 fixGlobalProductModel(), 863 fixGlobalProductModel(), 864 fixGlobalProductModel(), 865 } 866 867 ctx := context.TODO() 868 869 testCases := []struct { 870 Name string 871 PageSize int 872 RepositoryFn func() *automock.ProductRepository 873 ExpectedResult []*model.Product 874 ExpectedErrMessage string 875 }{ 876 { 877 Name: "Success", 878 RepositoryFn: func() *automock.ProductRepository { 879 repo := &automock.ProductRepository{} 880 repo.On("ListGlobal", ctx).Return(products, nil).Once() 881 return repo 882 }, 883 PageSize: 2, 884 ExpectedResult: products, 885 ExpectedErrMessage: "", 886 }, 887 { 888 Name: "Returns error when APIDefinition listing failed", 889 RepositoryFn: func() *automock.ProductRepository { 890 repo := &automock.ProductRepository{} 891 repo.On("ListGlobal", ctx).Return(nil, testErr).Once() 892 return repo 893 }, 894 PageSize: 2, 895 ExpectedResult: nil, 896 ExpectedErrMessage: testErr.Error(), 897 }, 898 } 899 900 for _, testCase := range testCases { 901 t.Run(testCase.Name, func(t *testing.T) { 902 repo := testCase.RepositoryFn() 903 904 svc := product.NewService(repo, nil) 905 906 // WHEN 907 docs, err := svc.ListGlobal(ctx) 908 909 // then 910 if testCase.ExpectedErrMessage == "" { 911 require.NoError(t, err) 912 assert.Equal(t, testCase.ExpectedResult, docs) 913 } else { 914 require.Error(t, err) 915 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 916 } 917 918 repo.AssertExpectations(t) 919 }) 920 } 921 } 922 923 func fixUIDService() *automock.UIDService { 924 svc := &automock.UIDService{} 925 svc.On("Generate").Return(productID).Once() 926 return svc 927 }