github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/spec/service_test.go (about) 1 package spec_test 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 "time" 8 9 "github.com/kyma-incubator/compass/components/director/internal/domain/spec" 10 "github.com/kyma-incubator/compass/components/director/internal/domain/spec/automock" 11 tnt "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/apperrors" 14 "github.com/kyma-incubator/compass/components/director/pkg/resource" 15 "github.com/pkg/errors" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/mock" 18 "github.com/stretchr/testify/require" 19 ) 20 21 const tenantID = "b91b59f7-2563-40b2-aba9-fef726037aa3" 22 23 var testErr = errors.New("Test error") 24 25 func TestService_GetByID(t *testing.T) { 26 testSpec := &model.Spec{} 27 28 testCases := []struct { 29 Name string 30 Context context.Context 31 SpecRepoMock *automock.SpecRepository 32 ExpectedResult *model.Spec 33 ExpectedError error 34 }{ 35 { 36 Name: "Success", 37 Context: tnt.SaveToContext(context.TODO(), tenantID, tenantID), 38 SpecRepoMock: func() *automock.SpecRepository { 39 specRepositoryMock := automock.SpecRepository{} 40 specRepositoryMock.On("GetByID", mock.Anything, tenantID, mock.Anything, mock.Anything).Return(testSpec, nil).Once() 41 return &specRepositoryMock 42 }(), 43 ExpectedResult: testSpec, 44 ExpectedError: nil, 45 }, 46 { 47 Name: "Fails when tenant is missing in context", 48 Context: context.TODO(), 49 SpecRepoMock: &automock.SpecRepository{}, 50 ExpectedResult: nil, 51 ExpectedError: apperrors.NewCannotReadTenantError(), 52 }, 53 { 54 Name: "Fails when repo get by id fails", 55 Context: tnt.SaveToContext(context.TODO(), tenantID, tenantID), 56 SpecRepoMock: func() *automock.SpecRepository { 57 specRepositoryMock := automock.SpecRepository{} 58 specRepositoryMock.On("GetByID", mock.Anything, tenantID, mock.Anything, mock.Anything).Return(nil, testErr).Once() 59 return &specRepositoryMock 60 }(), 61 ExpectedResult: testSpec, 62 ExpectedError: testErr, 63 }, 64 } 65 66 for _, testCase := range testCases { 67 t.Run(testCase.Name, func(t *testing.T) { 68 repo := testCase.SpecRepoMock 69 svc := spec.NewService(repo, nil, nil, nil) 70 71 // WHEN 72 spec, err := svc.GetByID(testCase.Context, "123", model.APISpecReference) 73 74 // then 75 if testCase.ExpectedError == nil { 76 require.NoError(t, err) 77 assert.Equal(t, testCase.ExpectedResult, spec) 78 } else { 79 require.Error(t, err) 80 assert.Equal(t, err, testCase.ExpectedError) 81 } 82 83 repo.AssertExpectations(t) 84 }) 85 } 86 } 87 88 func TestService_GetByIDGlobal(t *testing.T) { 89 testSpec := &model.Spec{} 90 91 testCases := []struct { 92 Name string 93 SpecRepoMock *automock.SpecRepository 94 ExpectedResult *model.Spec 95 ExpectedError error 96 }{ 97 { 98 Name: "Success", 99 SpecRepoMock: func() *automock.SpecRepository { 100 specRepositoryMock := automock.SpecRepository{} 101 specRepositoryMock.On("GetByIDGlobal", mock.Anything, specID).Return(testSpec, nil).Once() 102 return &specRepositoryMock 103 }(), 104 ExpectedResult: testSpec, 105 ExpectedError: nil, 106 }, 107 { 108 Name: "Fails when repo get by id fails", 109 SpecRepoMock: func() *automock.SpecRepository { 110 specRepositoryMock := automock.SpecRepository{} 111 specRepositoryMock.On("GetByIDGlobal", mock.Anything, specID).Return(nil, testErr).Once() 112 return &specRepositoryMock 113 }(), 114 ExpectedResult: testSpec, 115 ExpectedError: testErr, 116 }, 117 } 118 119 for _, testCase := range testCases { 120 t.Run(testCase.Name, func(t *testing.T) { 121 repo := testCase.SpecRepoMock 122 svc := spec.NewService(repo, nil, nil, nil) 123 124 // WHEN 125 spec, err := svc.GetByIDGlobal(context.TODO(), specID) 126 127 // then 128 if testCase.ExpectedError == nil { 129 require.NoError(t, err) 130 assert.Equal(t, testCase.ExpectedResult, spec) 131 } else { 132 require.Error(t, err) 133 assert.Equal(t, err, testCase.ExpectedError) 134 } 135 136 repo.AssertExpectations(t) 137 }) 138 } 139 } 140 141 func TestService_ListIDByReferenceObjectID(t *testing.T) { 142 // GIVEN 143 specIDs := []string{specID} 144 145 ctx := context.TODO() 146 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 147 148 testCases := []struct { 149 Name string 150 RepositoryFn func() *automock.SpecRepository 151 ResourceType resource.Type 152 ExpectedResult []string 153 ExpectedErrMessage string 154 }{ 155 { 156 Name: "Success for Application", 157 RepositoryFn: func() *automock.SpecRepository { 158 repo := &automock.SpecRepository{} 159 repo.On("ListIDByReferenceObjectID", ctx, tenant, model.APISpecReference, apiID).Return(specIDs, nil).Once() 160 return repo 161 }, 162 ResourceType: resource.Application, 163 ExpectedResult: specIDs, 164 ExpectedErrMessage: "", 165 }, 166 { 167 Name: "Success for Application Template Version", 168 RepositoryFn: func() *automock.SpecRepository { 169 repo := &automock.SpecRepository{} 170 repo.On("ListIDByReferenceObjectIDGlobal", ctx, model.APISpecReference, apiID).Return(specIDs, nil).Once() 171 return repo 172 }, 173 ResourceType: resource.ApplicationTemplateVersion, 174 ExpectedResult: specIDs, 175 ExpectedErrMessage: "", 176 }, 177 { 178 Name: "Returns error when APIDefinition listing failed for Application", 179 RepositoryFn: func() *automock.SpecRepository { 180 repo := &automock.SpecRepository{} 181 repo.On("ListIDByReferenceObjectID", ctx, tenant, model.APISpecReference, apiID).Return(nil, testErr).Once() 182 return repo 183 }, 184 ResourceType: resource.Application, 185 ExpectedResult: nil, 186 ExpectedErrMessage: testErr.Error(), 187 }, 188 { 189 Name: "Returns error when APIDefinition listing failed for Application Template Version", 190 RepositoryFn: func() *automock.SpecRepository { 191 repo := &automock.SpecRepository{} 192 repo.On("ListIDByReferenceObjectIDGlobal", ctx, model.APISpecReference, apiID).Return(nil, testErr).Once() 193 return repo 194 }, 195 ResourceType: resource.ApplicationTemplateVersion, 196 ExpectedResult: nil, 197 ExpectedErrMessage: testErr.Error(), 198 }, 199 } 200 201 for _, testCase := range testCases { 202 t.Run(testCase.Name, func(t *testing.T) { 203 repo := testCase.RepositoryFn() 204 205 svc := spec.NewService(repo, nil, nil, nil) 206 207 // WHEN 208 ids, err := svc.ListIDByReferenceObjectID(ctx, testCase.ResourceType, model.APISpecReference, apiID) 209 210 // then 211 if testCase.ExpectedErrMessage == "" { 212 require.NoError(t, err) 213 assert.Equal(t, testCase.ExpectedResult, ids) 214 } else { 215 require.Error(t, err) 216 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 217 } 218 219 repo.AssertExpectations(t) 220 }) 221 } 222 t.Run("Error when tenant not in context", func(t *testing.T) { 223 svc := spec.NewService(nil, nil, nil, nil) 224 // WHEN 225 _, err := svc.ListIDByReferenceObjectID(context.TODO(), resource.Application, model.APISpecReference, apiID) 226 // THEN 227 require.Error(t, err) 228 assert.Contains(t, err.Error(), "cannot read tenant from context") 229 }) 230 } 231 232 func TestService_ListByReferenceObjectID(t *testing.T) { 233 // GIVEN 234 specs := []*model.Spec{ 235 fixModelAPISpec(), 236 fixModelAPISpec(), 237 fixModelAPISpec(), 238 } 239 240 ctx := context.TODO() 241 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 242 243 testCases := []struct { 244 Name string 245 RepositoryFn func() *automock.SpecRepository 246 ExpectedResult []*model.Spec 247 ExpectedErrMessage string 248 }{ 249 { 250 Name: "Success", 251 RepositoryFn: func() *automock.SpecRepository { 252 repo := &automock.SpecRepository{} 253 repo.On("ListByReferenceObjectID", ctx, tenant, model.APISpecReference, apiID).Return(specs, nil).Once() 254 return repo 255 }, 256 ExpectedResult: specs, 257 ExpectedErrMessage: "", 258 }, 259 { 260 Name: "Returns error when APIDefinition listing failed", 261 RepositoryFn: func() *automock.SpecRepository { 262 repo := &automock.SpecRepository{} 263 repo.On("ListByReferenceObjectID", ctx, tenant, model.APISpecReference, apiID).Return(nil, testErr).Once() 264 return repo 265 }, 266 ExpectedResult: nil, 267 ExpectedErrMessage: testErr.Error(), 268 }, 269 } 270 271 for _, testCase := range testCases { 272 t.Run(testCase.Name, func(t *testing.T) { 273 repo := testCase.RepositoryFn() 274 275 svc := spec.NewService(repo, nil, nil, nil) 276 277 // WHEN 278 docs, err := svc.ListByReferenceObjectID(ctx, model.APISpecReference, apiID) 279 280 // then 281 if testCase.ExpectedErrMessage == "" { 282 require.NoError(t, err) 283 assert.Equal(t, testCase.ExpectedResult, docs) 284 } else { 285 require.Error(t, err) 286 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 287 } 288 289 repo.AssertExpectations(t) 290 }) 291 } 292 t.Run("Error when tenant not in context", func(t *testing.T) { 293 svc := spec.NewService(nil, nil, nil, nil) 294 // WHEN 295 _, err := svc.ListByReferenceObjectID(context.TODO(), model.APISpecReference, apiID) 296 // THEN 297 require.Error(t, err) 298 assert.Contains(t, err.Error(), "cannot read tenant from context") 299 }) 300 } 301 302 func TestService_ListByReferenceObjectIDs(t *testing.T) { 303 // GIVEN 304 testErr := errors.New("Test error") 305 firstAPIID := "apiID" 306 secondAPIID := "apiID2" 307 apiIDs := []string{firstAPIID, secondAPIID} 308 309 specForFirstAPI := fixModelAPISpecWithID(firstAPIID) 310 specForSecondAPI := fixModelAPISpecWithID(secondAPIID) 311 specs := []*model.Spec{specForFirstAPI, specForSecondAPI} 312 313 ctx := context.TODO() 314 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 315 316 testCases := []struct { 317 Name string 318 RepositoryFn func() *automock.SpecRepository 319 ExpectedResult []*model.Spec 320 ExpectedErrMessage string 321 }{ 322 { 323 Name: "Success", 324 RepositoryFn: func() *automock.SpecRepository { 325 repo := &automock.SpecRepository{} 326 repo.On("ListByReferenceObjectIDs", ctx, tenant, model.APISpecReference, apiIDs).Return(specs, nil).Once() 327 return repo 328 }, 329 ExpectedResult: specs, 330 }, 331 { 332 Name: "Returns error when Specs listing failed", 333 RepositoryFn: func() *automock.SpecRepository { 334 repo := &automock.SpecRepository{} 335 repo.On("ListByReferenceObjectIDs", ctx, tenant, model.APISpecReference, apiIDs).Return(nil, testErr).Once() 336 return repo 337 }, 338 ExpectedResult: nil, 339 ExpectedErrMessage: testErr.Error(), 340 }, 341 } 342 343 for _, testCase := range testCases { 344 t.Run(testCase.Name, func(t *testing.T) { 345 repo := testCase.RepositoryFn() 346 347 svc := spec.NewService(repo, nil, nil, nil) 348 349 // WHEN 350 specifications, err := svc.ListByReferenceObjectIDs(ctx, model.APISpecReference, apiIDs) 351 352 // then 353 if testCase.ExpectedErrMessage == "" { 354 require.NoError(t, err) 355 assert.Equal(t, testCase.ExpectedResult, specifications) 356 } else { 357 require.Error(t, err) 358 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 359 } 360 361 repo.AssertExpectations(t) 362 }) 363 } 364 t.Run("Error when tenant not in context", func(t *testing.T) { 365 svc := spec.NewService(nil, nil, nil, nil) 366 // WHEN 367 _, err := svc.ListByReferenceObjectIDs(context.TODO(), model.APISpecReference, apiIDs) 368 // THEN 369 require.Error(t, err) 370 assert.Contains(t, err.Error(), "cannot read tenant from context") 371 }) 372 } 373 374 func TestService_DeleteByReferenceObjectID(t *testing.T) { 375 // GIVEN 376 testErr := errors.New("Test error") 377 378 specs := []*model.Spec{ 379 fixModelAPISpec(), 380 fixModelAPISpec(), 381 fixModelAPISpec(), 382 } 383 384 ctx := context.TODO() 385 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 386 387 testCases := []struct { 388 Name string 389 RepositoryFn func() *automock.SpecRepository 390 ExpectedResult []*model.Spec 391 ResourceType resource.Type 392 ExpectedErrMessage string 393 }{ 394 { 395 Name: "Success for Application", 396 RepositoryFn: func() *automock.SpecRepository { 397 repo := &automock.SpecRepository{} 398 repo.On("DeleteByReferenceObjectID", ctx, tenant, model.APISpecReference, apiID).Return(nil).Once() 399 return repo 400 }, 401 ResourceType: resource.Application, 402 ExpectedResult: specs, 403 ExpectedErrMessage: "", 404 }, 405 { 406 Name: "Success for Application Template Version", 407 RepositoryFn: func() *automock.SpecRepository { 408 repo := &automock.SpecRepository{} 409 repo.On("DeleteByReferenceObjectIDGlobal", ctx, model.APISpecReference, apiID).Return(nil).Once() 410 return repo 411 }, 412 ResourceType: resource.ApplicationTemplateVersion, 413 ExpectedResult: specs, 414 ExpectedErrMessage: "", 415 }, 416 { 417 Name: "Returns error when APIDefinition listing failed for Application", 418 RepositoryFn: func() *automock.SpecRepository { 419 repo := &automock.SpecRepository{} 420 repo.On("DeleteByReferenceObjectID", ctx, tenant, model.APISpecReference, apiID).Return(testErr).Once() 421 return repo 422 }, 423 ResourceType: resource.Application, 424 ExpectedResult: nil, 425 ExpectedErrMessage: testErr.Error(), 426 }, 427 { 428 Name: "Returns error when APIDefinition listing failed for Application", 429 RepositoryFn: func() *automock.SpecRepository { 430 repo := &automock.SpecRepository{} 431 repo.On("DeleteByReferenceObjectIDGlobal", ctx, model.APISpecReference, apiID).Return(testErr).Once() 432 return repo 433 }, 434 ResourceType: resource.ApplicationTemplateVersion, 435 ExpectedResult: nil, 436 ExpectedErrMessage: testErr.Error(), 437 }, 438 } 439 440 for _, testCase := range testCases { 441 t.Run(testCase.Name, func(t *testing.T) { 442 repo := testCase.RepositoryFn() 443 444 svc := spec.NewService(repo, nil, nil, nil) 445 446 // WHEN 447 err := svc.DeleteByReferenceObjectID(ctx, testCase.ResourceType, model.APISpecReference, apiID) 448 449 // then 450 if testCase.ExpectedErrMessage == "" { 451 require.NoError(t, err) 452 } else { 453 require.Error(t, err) 454 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 455 } 456 457 repo.AssertExpectations(t) 458 }) 459 } 460 t.Run("Error when tenant not in context", func(t *testing.T) { 461 svc := spec.NewService(nil, nil, nil, nil) 462 // WHEN 463 err := svc.DeleteByReferenceObjectID(context.TODO(), resource.Application, model.APISpecReference, apiID) 464 // THEN 465 require.Error(t, err) 466 assert.Contains(t, err.Error(), "cannot read tenant from context") 467 }) 468 } 469 470 func TestService_GetByReferenceObjectID(t *testing.T) { 471 // GIVEN 472 testErr := errors.New("Test error") 473 474 specs := []*model.Spec{ 475 fixModelAPISpec(), 476 fixModelAPISpec(), 477 fixModelAPISpec(), 478 } 479 480 ctx := context.TODO() 481 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 482 483 testCases := []struct { 484 Name string 485 RepositoryFn func() *automock.SpecRepository 486 ResourceType resource.Type 487 ExpectedResult *model.Spec 488 ExpectedErrMessage string 489 }{ 490 { 491 Name: "Success for Application", 492 RepositoryFn: func() *automock.SpecRepository { 493 repo := &automock.SpecRepository{} 494 repo.On("ListByReferenceObjectID", ctx, tenant, model.APISpecReference, apiID).Return(specs, nil).Once() 495 return repo 496 }, 497 ResourceType: resource.Application, 498 ExpectedResult: specs[0], 499 ExpectedErrMessage: "", 500 }, 501 { 502 Name: "Success for Application Template Version", 503 RepositoryFn: func() *automock.SpecRepository { 504 repo := &automock.SpecRepository{} 505 repo.On("ListByReferenceObjectIDGlobal", ctx, model.APISpecReference, apiID).Return(specs, nil).Once() 506 return repo 507 }, 508 ResourceType: resource.ApplicationTemplateVersion, 509 ExpectedResult: specs[0], 510 ExpectedErrMessage: "", 511 }, 512 { 513 Name: "Returns error when APIDefinition listing failed for Application", 514 RepositoryFn: func() *automock.SpecRepository { 515 repo := &automock.SpecRepository{} 516 repo.On("ListByReferenceObjectID", ctx, tenant, model.APISpecReference, apiID).Return(nil, testErr).Once() 517 return repo 518 }, 519 ResourceType: resource.Application, 520 ExpectedResult: nil, 521 ExpectedErrMessage: testErr.Error(), 522 }, 523 { 524 Name: "Returns error when APIDefinition listing failed for Application Template Version", 525 RepositoryFn: func() *automock.SpecRepository { 526 repo := &automock.SpecRepository{} 527 repo.On("ListByReferenceObjectIDGlobal", ctx, model.APISpecReference, apiID).Return(nil, testErr).Once() 528 return repo 529 }, 530 ResourceType: resource.ApplicationTemplateVersion, 531 ExpectedResult: nil, 532 ExpectedErrMessage: testErr.Error(), 533 }, 534 { 535 Name: "Returns nil when no specs are found", 536 RepositoryFn: func() *automock.SpecRepository { 537 repo := &automock.SpecRepository{} 538 repo.On("ListByReferenceObjectID", ctx, tenant, model.APISpecReference, apiID).Return([]*model.Spec{}, nil).Once() 539 return repo 540 }, 541 ResourceType: resource.Application, 542 ExpectedResult: nil, 543 }, 544 } 545 546 for _, testCase := range testCases { 547 t.Run(testCase.Name, func(t *testing.T) { 548 repo := testCase.RepositoryFn() 549 550 svc := spec.NewService(repo, nil, nil, nil) 551 552 // WHEN 553 docs, err := svc.GetByReferenceObjectID(ctx, testCase.ResourceType, model.APISpecReference, apiID) 554 555 // then 556 if testCase.ExpectedErrMessage == "" { 557 require.NoError(t, err) 558 assert.Equal(t, testCase.ExpectedResult, docs) 559 } else { 560 require.Error(t, err) 561 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 562 } 563 564 repo.AssertExpectations(t) 565 }) 566 } 567 t.Run("Error when tenant not in context", func(t *testing.T) { 568 svc := spec.NewService(nil, nil, nil, nil) 569 // WHEN 570 _, err := svc.GetByReferenceObjectID(context.TODO(), resource.Application, model.APISpecReference, apiID) 571 // THEN 572 require.Error(t, err) 573 assert.Contains(t, err.Error(), "cannot read tenant from context") 574 }) 575 } 576 577 func TestService_CreateByReferenceObjectID(t *testing.T) { 578 // GIVEN 579 testErr := errors.New("Test error") 580 581 ctx := context.TODO() 582 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 583 584 specData := "specData" 585 586 specInputWithFR := fixModelAPISpecInputWithFetchRequest() 587 specInputWithFR.Data = nil 588 589 specModel := fixModelAPISpec() 590 specModel.Data = nil 591 592 timestamp := time.Now() 593 594 fr := &model.FetchRequest{ 595 ID: specID, 596 URL: "foo.bar", 597 Mode: model.FetchModeSingle, 598 Status: &model.FetchRequestStatus{ 599 Condition: model.FetchRequestStatusConditionInitial, 600 Timestamp: timestamp, 601 }, 602 ObjectType: model.APISpecFetchRequestReference, 603 ObjectID: specID, 604 } 605 606 testCases := []struct { 607 Name string 608 RepositoryFn func() *automock.SpecRepository 609 FetchRequestRepoFn func() *automock.FetchRequestRepository 610 UIDServiceFn func() *automock.UIDService 611 FetchRequestServiceFn func() *automock.FetchRequestService 612 ResourceType resource.Type 613 Input model.SpecInput 614 ExpectedErr error 615 }{ 616 { 617 Name: "Success for Application", 618 RepositoryFn: func() *automock.SpecRepository { 619 repo := &automock.SpecRepository{} 620 repo.On("Create", ctx, tenant, specModel).Return(nil).Once() 621 repo.On("Update", ctx, tenant, specModel).Return(nil).Once() 622 return repo 623 }, 624 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 625 repo := &automock.FetchRequestRepository{} 626 repo.On("Create", ctx, tenant, fr).Return(nil).Once() 627 628 return repo 629 }, 630 UIDServiceFn: func() *automock.UIDService { 631 svc := &automock.UIDService{} 632 svc.On("Generate").Return(specID).Twice() 633 return svc 634 }, 635 FetchRequestServiceFn: func() *automock.FetchRequestService { 636 svc := &automock.FetchRequestService{} 637 svc.On("HandleSpec", ctx, fr).Return(nil) 638 return svc 639 }, 640 ResourceType: resource.Application, 641 Input: *specInputWithFR, 642 ExpectedErr: nil, 643 }, 644 { 645 Name: "Success for Application Template Version", 646 RepositoryFn: func() *automock.SpecRepository { 647 repo := &automock.SpecRepository{} 648 repo.On("CreateGlobal", ctx, specModel).Return(nil).Once() 649 repo.On("UpdateGlobal", ctx, specModel).Return(nil).Once() 650 return repo 651 }, 652 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 653 repo := &automock.FetchRequestRepository{} 654 repo.On("CreateGlobal", ctx, fr).Return(nil).Once() 655 656 return repo 657 }, 658 UIDServiceFn: func() *automock.UIDService { 659 svc := &automock.UIDService{} 660 svc.On("Generate").Return(specID).Twice() 661 return svc 662 }, 663 FetchRequestServiceFn: func() *automock.FetchRequestService { 664 svc := &automock.FetchRequestService{} 665 svc.On("HandleSpec", ctx, fr).Return(nil) 666 return svc 667 }, 668 ResourceType: resource.ApplicationTemplateVersion, 669 Input: *specInputWithFR, 670 ExpectedErr: nil, 671 }, 672 { 673 Name: "Success fetched Spec", 674 RepositoryFn: func() *automock.SpecRepository { 675 repo := &automock.SpecRepository{} 676 repo.On("Create", ctx, tenant, specModel).Return(nil).Once() 677 repo.On("Update", ctx, tenant, fixModelAPISpec()).Return(nil).Once() 678 679 return repo 680 }, 681 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 682 repo := &automock.FetchRequestRepository{} 683 repo.On("Create", ctx, tenant, fr).Return(nil).Once() 684 685 return repo 686 }, 687 UIDServiceFn: func() *automock.UIDService { 688 svc := &automock.UIDService{} 689 svc.On("Generate").Return(specID).Twice() 690 return svc 691 }, 692 FetchRequestServiceFn: func() *automock.FetchRequestService { 693 svc := &automock.FetchRequestService{} 694 svc.On("HandleSpec", ctx, fr).Return(&specData) 695 return svc 696 }, 697 ResourceType: resource.Application, 698 Input: *specInputWithFR, 699 ExpectedErr: nil, 700 }, 701 { 702 Name: "Error - Spec Creation for Application", 703 RepositoryFn: func() *automock.SpecRepository { 704 repo := &automock.SpecRepository{} 705 repo.On("Create", ctx, tenant, specModel).Return(testErr).Once() 706 return repo 707 }, 708 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 709 return &automock.FetchRequestRepository{} 710 }, 711 UIDServiceFn: func() *automock.UIDService { 712 svc := &automock.UIDService{} 713 svc.On("Generate").Return(specID).Once() 714 return svc 715 }, 716 FetchRequestServiceFn: func() *automock.FetchRequestService { 717 return &automock.FetchRequestService{} 718 }, 719 ResourceType: resource.Application, 720 Input: *specInputWithFR, 721 ExpectedErr: testErr, 722 }, 723 { 724 Name: "Error - Spec Creation for Application Template Version", 725 RepositoryFn: func() *automock.SpecRepository { 726 repo := &automock.SpecRepository{} 727 repo.On("CreateGlobal", ctx, specModel).Return(testErr).Once() 728 return repo 729 }, 730 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 731 return &automock.FetchRequestRepository{} 732 }, 733 UIDServiceFn: func() *automock.UIDService { 734 svc := &automock.UIDService{} 735 svc.On("Generate").Return(specID).Once() 736 return svc 737 }, 738 FetchRequestServiceFn: func() *automock.FetchRequestService { 739 return &automock.FetchRequestService{} 740 }, 741 ResourceType: resource.ApplicationTemplateVersion, 742 Input: *specInputWithFR, 743 ExpectedErr: testErr, 744 }, 745 { 746 Name: "Error - Fetch Request Creation for Application", 747 RepositoryFn: func() *automock.SpecRepository { 748 repo := &automock.SpecRepository{} 749 repo.On("Create", ctx, tenant, specModel).Return(nil).Once() 750 return repo 751 }, 752 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 753 repo := &automock.FetchRequestRepository{} 754 repo.On("Create", ctx, tenant, fr).Return(testErr).Once() 755 return repo 756 }, 757 UIDServiceFn: func() *automock.UIDService { 758 svc := &automock.UIDService{} 759 svc.On("Generate").Return(specID).Twice() 760 return svc 761 }, 762 FetchRequestServiceFn: func() *automock.FetchRequestService { 763 return &automock.FetchRequestService{} 764 }, 765 ResourceType: resource.Application, 766 Input: *specInputWithFR, 767 ExpectedErr: testErr, 768 }, 769 { 770 Name: "Error - Fetch Request Creation for Application Template Version", 771 RepositoryFn: func() *automock.SpecRepository { 772 repo := &automock.SpecRepository{} 773 repo.On("CreateGlobal", ctx, specModel).Return(nil).Once() 774 return repo 775 }, 776 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 777 repo := &automock.FetchRequestRepository{} 778 repo.On("CreateGlobal", ctx, fr).Return(testErr).Once() 779 return repo 780 }, 781 UIDServiceFn: func() *automock.UIDService { 782 svc := &automock.UIDService{} 783 svc.On("Generate").Return(specID).Twice() 784 return svc 785 }, 786 FetchRequestServiceFn: func() *automock.FetchRequestService { 787 return &automock.FetchRequestService{} 788 }, 789 ResourceType: resource.ApplicationTemplateVersion, 790 Input: *specInputWithFR, 791 ExpectedErr: testErr, 792 }, 793 { 794 Name: "Error - Spec Update for Application", 795 RepositoryFn: func() *automock.SpecRepository { 796 repo := &automock.SpecRepository{} 797 repo.On("Create", ctx, tenant, specModel).Return(nil).Once() 798 repo.On("Update", ctx, tenant, specModel).Return(testErr).Once() 799 800 return repo 801 }, 802 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 803 repo := &automock.FetchRequestRepository{} 804 repo.On("Create", ctx, tenant, fr).Return(nil).Once() 805 return repo 806 }, 807 UIDServiceFn: func() *automock.UIDService { 808 svc := &automock.UIDService{} 809 svc.On("Generate").Return(specID).Twice() 810 return svc 811 }, 812 FetchRequestServiceFn: func() *automock.FetchRequestService { 813 svc := &automock.FetchRequestService{} 814 svc.On("HandleSpec", ctx, fr).Return(nil) 815 return svc 816 }, 817 ResourceType: resource.Application, 818 Input: *specInputWithFR, 819 ExpectedErr: testErr, 820 }, 821 { 822 Name: "Error - Spec Update for Application Template Version", 823 RepositoryFn: func() *automock.SpecRepository { 824 repo := &automock.SpecRepository{} 825 repo.On("CreateGlobal", ctx, specModel).Return(nil).Once() 826 repo.On("UpdateGlobal", ctx, specModel).Return(testErr).Once() 827 828 return repo 829 }, 830 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 831 repo := &automock.FetchRequestRepository{} 832 repo.On("CreateGlobal", ctx, fr).Return(nil).Once() 833 return repo 834 }, 835 UIDServiceFn: func() *automock.UIDService { 836 svc := &automock.UIDService{} 837 svc.On("Generate").Return(specID).Twice() 838 return svc 839 }, 840 FetchRequestServiceFn: func() *automock.FetchRequestService { 841 svc := &automock.FetchRequestService{} 842 svc.On("HandleSpec", ctx, fr).Return(nil) 843 return svc 844 }, 845 ResourceType: resource.ApplicationTemplateVersion, 846 Input: *specInputWithFR, 847 ExpectedErr: testErr, 848 }, 849 } 850 851 for _, testCase := range testCases { 852 t.Run(testCase.Name, func(t *testing.T) { 853 // GIVEN 854 repo := testCase.RepositoryFn() 855 fetchRequestRepo := testCase.FetchRequestRepoFn() 856 uidService := testCase.UIDServiceFn() 857 fetchRequestService := testCase.FetchRequestServiceFn() 858 859 svc := spec.NewService(repo, fetchRequestRepo, uidService, fetchRequestService) 860 svc.SetTimestampGen(func() time.Time { 861 return timestamp 862 }) 863 864 // WHEN 865 result, err := svc.CreateByReferenceObjectID(ctx, testCase.Input, testCase.ResourceType, model.APISpecReference, apiID) 866 867 // then 868 if testCase.ExpectedErr != nil { 869 require.Error(t, err) 870 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 871 } else { 872 assert.IsType(t, "string", result) 873 } 874 875 repo.AssertExpectations(t) 876 fetchRequestRepo.AssertExpectations(t) 877 uidService.AssertExpectations(t) 878 }) 879 } 880 t.Run("Error when tenant not in context", func(t *testing.T) { 881 svc := spec.NewService(nil, nil, fixUIDService(), nil) 882 // WHEN 883 _, err := svc.CreateByReferenceObjectID(context.TODO(), *fixModelAPISpecInput(), resource.Application, model.APISpecReference, apiID) 884 // THEN 885 require.Error(t, err) 886 assert.Contains(t, err.Error(), "cannot read tenant from context") 887 }) 888 } 889 890 func TestService_CreateByReferenceObjectIDWithDelayedFetchRequest(t *testing.T) { 891 // GIVEN 892 testErr := errors.New("Test error") 893 894 ctx := context.TODO() 895 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 896 897 specInputWithFR := fixModelAPISpecInputWithFetchRequest() 898 specInputWithFR.Data = nil 899 900 specInputWithEmptyAPIType := fixModelAPISpecInputWithFetchRequest() 901 specInputWithEmptyAPIType.APIType = nil 902 903 specModel := fixModelAPISpec() 904 specModel.Data = nil 905 906 timestamp := time.Now() 907 908 fr := &model.FetchRequest{ 909 ID: specID, 910 URL: "foo.bar", 911 Mode: model.FetchModeSingle, 912 Status: &model.FetchRequestStatus{ 913 Condition: model.FetchRequestStatusConditionInitial, 914 Timestamp: timestamp, 915 }, 916 ObjectType: model.APISpecFetchRequestReference, 917 ObjectID: specID, 918 } 919 920 testCases := []struct { 921 Name string 922 RepositoryFn func() *automock.SpecRepository 923 FetchRequestRepoFn func() *automock.FetchRequestRepository 924 UIDServiceFn func() *automock.UIDService 925 Input model.SpecInput 926 ResourceType resource.Type 927 ExpectedErr error 928 }{ 929 { 930 Name: "Success for Application", 931 RepositoryFn: func() *automock.SpecRepository { 932 repo := &automock.SpecRepository{} 933 repo.On("Create", ctx, tenant, specModel).Return(nil).Once() 934 935 return repo 936 }, 937 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 938 repo := &automock.FetchRequestRepository{} 939 repo.On("Create", ctx, tenant, fr).Return(nil).Once() 940 941 return repo 942 }, 943 UIDServiceFn: func() *automock.UIDService { 944 svc := &automock.UIDService{} 945 svc.On("Generate").Return(specID).Twice() 946 return svc 947 }, 948 Input: *specInputWithFR, 949 ResourceType: resource.Application, 950 ExpectedErr: nil, 951 }, 952 { 953 Name: "Success for Application Template Version", 954 RepositoryFn: func() *automock.SpecRepository { 955 repo := &automock.SpecRepository{} 956 repo.On("CreateGlobal", ctx, specModel).Return(nil).Once() 957 958 return repo 959 }, 960 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 961 repo := &automock.FetchRequestRepository{} 962 repo.On("CreateGlobal", ctx, fr).Return(nil).Once() 963 964 return repo 965 }, 966 UIDServiceFn: func() *automock.UIDService { 967 svc := &automock.UIDService{} 968 svc.On("Generate").Return(specID).Twice() 969 return svc 970 }, 971 Input: *specInputWithFR, 972 ResourceType: resource.ApplicationTemplateVersion, 973 ExpectedErr: nil, 974 }, 975 { 976 Name: "Error - spec conversion", 977 RepositoryFn: func() *automock.SpecRepository { 978 return &automock.SpecRepository{} 979 }, 980 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 981 return &automock.FetchRequestRepository{} 982 }, 983 UIDServiceFn: func() *automock.UIDService { 984 svc := &automock.UIDService{} 985 svc.On("Generate").Return(specID).Once() 986 return svc 987 }, 988 Input: *specInputWithEmptyAPIType, 989 ResourceType: resource.Application, 990 ExpectedErr: errors.New("API Spec type cannot be empty"), 991 }, 992 { 993 Name: "Error - Spec Creation for Application", 994 RepositoryFn: func() *automock.SpecRepository { 995 repo := &automock.SpecRepository{} 996 repo.On("Create", ctx, tenant, specModel).Return(testErr).Once() 997 return repo 998 }, 999 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1000 return &automock.FetchRequestRepository{} 1001 }, 1002 UIDServiceFn: func() *automock.UIDService { 1003 svc := &automock.UIDService{} 1004 svc.On("Generate").Return(specID).Once() 1005 return svc 1006 }, 1007 Input: *specInputWithFR, 1008 ResourceType: resource.Application, 1009 ExpectedErr: testErr, 1010 }, 1011 { 1012 Name: "Error - Spec Creation for Application Template Version", 1013 RepositoryFn: func() *automock.SpecRepository { 1014 repo := &automock.SpecRepository{} 1015 repo.On("CreateGlobal", ctx, specModel).Return(testErr).Once() 1016 return repo 1017 }, 1018 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1019 return &automock.FetchRequestRepository{} 1020 }, 1021 UIDServiceFn: func() *automock.UIDService { 1022 svc := &automock.UIDService{} 1023 svc.On("Generate").Return(specID).Once() 1024 return svc 1025 }, 1026 Input: *specInputWithFR, 1027 ResourceType: resource.ApplicationTemplateVersion, 1028 ExpectedErr: testErr, 1029 }, 1030 { 1031 Name: "Error - Fetch Request Creation for Application", 1032 RepositoryFn: func() *automock.SpecRepository { 1033 repo := &automock.SpecRepository{} 1034 repo.On("Create", ctx, tenant, specModel).Return(nil).Once() 1035 return repo 1036 }, 1037 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1038 repo := &automock.FetchRequestRepository{} 1039 repo.On("Create", ctx, tenant, fr).Return(testErr).Once() 1040 return repo 1041 }, 1042 UIDServiceFn: func() *automock.UIDService { 1043 svc := &automock.UIDService{} 1044 svc.On("Generate").Return(specID).Twice() 1045 return svc 1046 }, 1047 Input: *specInputWithFR, 1048 ResourceType: resource.Application, 1049 ExpectedErr: testErr, 1050 }, 1051 { 1052 Name: "Error - Fetch Request Creation for Application Template Version", 1053 RepositoryFn: func() *automock.SpecRepository { 1054 repo := &automock.SpecRepository{} 1055 repo.On("CreateGlobal", ctx, specModel).Return(nil).Once() 1056 return repo 1057 }, 1058 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1059 repo := &automock.FetchRequestRepository{} 1060 repo.On("CreateGlobal", ctx, fr).Return(testErr).Once() 1061 return repo 1062 }, 1063 UIDServiceFn: func() *automock.UIDService { 1064 svc := &automock.UIDService{} 1065 svc.On("Generate").Return(specID).Twice() 1066 return svc 1067 }, 1068 Input: *specInputWithFR, 1069 ResourceType: resource.ApplicationTemplateVersion, 1070 ExpectedErr: testErr, 1071 }, 1072 } 1073 1074 for _, testCase := range testCases { 1075 t.Run(testCase.Name, func(t *testing.T) { 1076 // GIVEN 1077 repo := testCase.RepositoryFn() 1078 fetchRequestRepo := testCase.FetchRequestRepoFn() 1079 uidService := testCase.UIDServiceFn() 1080 1081 svc := spec.NewService(repo, fetchRequestRepo, uidService, nil) 1082 svc.SetTimestampGen(func() time.Time { 1083 return timestamp 1084 }) 1085 1086 // WHEN 1087 result, fr, err := svc.CreateByReferenceObjectIDWithDelayedFetchRequest(ctx, testCase.Input, testCase.ResourceType, model.APISpecReference, apiID) 1088 1089 // then 1090 if testCase.ExpectedErr != nil { 1091 require.Error(t, err) 1092 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 1093 } else { 1094 assert.IsType(t, "string", result) 1095 assert.NotEmpty(t, fr) 1096 } 1097 1098 repo.AssertExpectations(t) 1099 fetchRequestRepo.AssertExpectations(t) 1100 uidService.AssertExpectations(t) 1101 }) 1102 } 1103 t.Run("Error when tenant not in context", func(t *testing.T) { 1104 svc := spec.NewService(nil, nil, fixUIDService(), nil) 1105 // WHEN 1106 _, _, err := svc.CreateByReferenceObjectIDWithDelayedFetchRequest(context.TODO(), *fixModelAPISpecInput(), resource.Application, model.APISpecReference, apiID) 1107 // THEN 1108 require.Error(t, err) 1109 assert.Contains(t, err.Error(), "cannot read tenant from context") 1110 }) 1111 } 1112 1113 func TestService_UpdateByReferenceObjectID(t *testing.T) { 1114 // GIVEN 1115 testErr := errors.New("Test error") 1116 1117 ctx := context.TODO() 1118 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 1119 1120 specData := "specData" 1121 1122 specInputWithFR := fixModelAPISpecInputWithFetchRequest() 1123 specInputWithFR.Data = nil 1124 1125 specModel := fixModelAPISpec() 1126 specModel.Data = nil 1127 1128 timestamp := time.Now() 1129 1130 fr := &model.FetchRequest{ 1131 ID: specID, 1132 URL: "foo.bar", 1133 Mode: model.FetchModeSingle, 1134 Status: &model.FetchRequestStatus{ 1135 Condition: model.FetchRequestStatusConditionInitial, 1136 Timestamp: timestamp, 1137 }, 1138 ObjectType: model.APISpecFetchRequestReference, 1139 ObjectID: specID, 1140 } 1141 1142 testCases := []struct { 1143 Name string 1144 RepositoryFn func() *automock.SpecRepository 1145 FetchRequestRepoFn func() *automock.FetchRequestRepository 1146 UIDServiceFn func() *automock.UIDService 1147 FetchRequestServiceFn func() *automock.FetchRequestService 1148 ResourceType resource.Type 1149 Input model.SpecInput 1150 InputID string 1151 ExpectedErr error 1152 }{ 1153 { 1154 Name: "Success for Application", 1155 RepositoryFn: func() *automock.SpecRepository { 1156 repo := &automock.SpecRepository{} 1157 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(specModel, nil).Once() 1158 repo.On("Update", ctx, tenant, fixModelAPISpec()).Return(nil).Once() 1159 return repo 1160 }, 1161 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1162 repo := &automock.FetchRequestRepository{} 1163 repo.On("DeleteByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(nil).Once() 1164 repo.On("Create", ctx, tenant, fr).Return(nil).Once() 1165 1166 return repo 1167 }, 1168 UIDServiceFn: func() *automock.UIDService { 1169 svc := &automock.UIDService{} 1170 svc.On("Generate").Return(specID).Once() 1171 return svc 1172 }, 1173 FetchRequestServiceFn: func() *automock.FetchRequestService { 1174 svc := &automock.FetchRequestService{} 1175 svc.On("HandleSpec", ctx, fr).Return(&specData) 1176 return svc 1177 }, 1178 ResourceType: resource.Application, 1179 InputID: specID, 1180 Input: *specInputWithFR, 1181 ExpectedErr: nil, 1182 }, 1183 { 1184 Name: "Success for Application Template Version", 1185 RepositoryFn: func() *automock.SpecRepository { 1186 repo := &automock.SpecRepository{} 1187 repo.On("GetByIDGlobal", ctx, specID).Return(specModel, nil).Once() 1188 repo.On("UpdateGlobal", ctx, fixModelAPISpec()).Return(nil).Once() 1189 return repo 1190 }, 1191 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1192 repo := &automock.FetchRequestRepository{} 1193 repo.On("DeleteByReferenceObjectIDGlobal", ctx, model.APISpecFetchRequestReference, specID).Return(nil).Once() 1194 repo.On("CreateGlobal", ctx, fr).Return(nil).Once() 1195 1196 return repo 1197 }, 1198 UIDServiceFn: func() *automock.UIDService { 1199 svc := &automock.UIDService{} 1200 svc.On("Generate").Return(specID).Once() 1201 return svc 1202 }, 1203 FetchRequestServiceFn: func() *automock.FetchRequestService { 1204 svc := &automock.FetchRequestService{} 1205 svc.On("HandleSpec", ctx, fr).Return(&specData) 1206 return svc 1207 }, 1208 ResourceType: resource.ApplicationTemplateVersion, 1209 InputID: specID, 1210 Input: *specInputWithFR, 1211 ExpectedErr: nil, 1212 }, 1213 { 1214 Name: "Update Error For Application", 1215 RepositoryFn: func() *automock.SpecRepository { 1216 repo := &automock.SpecRepository{} 1217 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(specModel, nil).Once() 1218 repo.On("Update", ctx, tenant, specModel).Return(testErr).Once() 1219 return repo 1220 }, 1221 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1222 repo := &automock.FetchRequestRepository{} 1223 repo.On("DeleteByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(nil).Once() 1224 repo.On("Create", ctx, tenant, fr).Return(nil).Once() 1225 1226 return repo 1227 }, 1228 UIDServiceFn: func() *automock.UIDService { 1229 svc := &automock.UIDService{} 1230 svc.On("Generate").Return(specID).Once() 1231 return svc 1232 }, 1233 FetchRequestServiceFn: func() *automock.FetchRequestService { 1234 svc := &automock.FetchRequestService{} 1235 svc.On("HandleSpec", ctx, fr).Return(nil) 1236 return svc 1237 }, 1238 ResourceType: resource.Application, 1239 InputID: specID, 1240 Input: *specInputWithFR, 1241 ExpectedErr: testErr, 1242 }, 1243 { 1244 Name: "Update Error For Application Template Version", 1245 RepositoryFn: func() *automock.SpecRepository { 1246 repo := &automock.SpecRepository{} 1247 repo.On("GetByIDGlobal", ctx, specID).Return(specModel, nil).Once() 1248 repo.On("UpdateGlobal", ctx, specModel).Return(testErr).Once() 1249 return repo 1250 }, 1251 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1252 repo := &automock.FetchRequestRepository{} 1253 repo.On("DeleteByReferenceObjectIDGlobal", ctx, model.APISpecFetchRequestReference, specID).Return(nil).Once() 1254 repo.On("CreateGlobal", ctx, fr).Return(nil).Once() 1255 1256 return repo 1257 }, 1258 UIDServiceFn: func() *automock.UIDService { 1259 svc := &automock.UIDService{} 1260 svc.On("Generate").Return(specID).Once() 1261 return svc 1262 }, 1263 FetchRequestServiceFn: func() *automock.FetchRequestService { 1264 svc := &automock.FetchRequestService{} 1265 svc.On("HandleSpec", ctx, fr).Return(nil) 1266 return svc 1267 }, 1268 ResourceType: resource.ApplicationTemplateVersion, 1269 InputID: specID, 1270 Input: *specInputWithFR, 1271 ExpectedErr: testErr, 1272 }, 1273 { 1274 Name: "Delete FetchRequest by reference Error for Application", 1275 RepositoryFn: func() *automock.SpecRepository { 1276 repo := &automock.SpecRepository{} 1277 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(specModel, nil).Once() 1278 return repo 1279 }, 1280 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1281 repo := &automock.FetchRequestRepository{} 1282 repo.On("DeleteByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(testErr).Once() 1283 return repo 1284 }, 1285 UIDServiceFn: func() *automock.UIDService { 1286 svc := &automock.UIDService{} 1287 return svc 1288 }, 1289 FetchRequestServiceFn: func() *automock.FetchRequestService { 1290 svc := &automock.FetchRequestService{} 1291 return svc 1292 }, 1293 ResourceType: resource.Application, 1294 InputID: specID, 1295 Input: *specInputWithFR, 1296 ExpectedErr: testErr, 1297 }, 1298 { 1299 Name: "Delete FetchRequest by reference Error for Application Template Version", 1300 RepositoryFn: func() *automock.SpecRepository { 1301 repo := &automock.SpecRepository{} 1302 repo.On("GetByIDGlobal", ctx, specID).Return(specModel, nil).Once() 1303 return repo 1304 }, 1305 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1306 repo := &automock.FetchRequestRepository{} 1307 repo.On("DeleteByReferenceObjectIDGlobal", ctx, model.APISpecFetchRequestReference, specID).Return(testErr).Once() 1308 return repo 1309 }, 1310 UIDServiceFn: func() *automock.UIDService { 1311 svc := &automock.UIDService{} 1312 return svc 1313 }, 1314 FetchRequestServiceFn: func() *automock.FetchRequestService { 1315 svc := &automock.FetchRequestService{} 1316 return svc 1317 }, 1318 ResourceType: resource.ApplicationTemplateVersion, 1319 InputID: specID, 1320 Input: *specInputWithFR, 1321 ExpectedErr: testErr, 1322 }, 1323 { 1324 Name: "Fetch Request Creation Error for Application", 1325 RepositoryFn: func() *automock.SpecRepository { 1326 repo := &automock.SpecRepository{} 1327 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(specModel, nil).Once() 1328 return repo 1329 }, 1330 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1331 repo := &automock.FetchRequestRepository{} 1332 repo.On("DeleteByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(nil).Once() 1333 repo.On("Create", ctx, tenant, fr).Return(testErr).Once() 1334 return repo 1335 }, 1336 UIDServiceFn: func() *automock.UIDService { 1337 svc := &automock.UIDService{} 1338 svc.On("Generate").Return(specID).Once() 1339 return svc 1340 }, 1341 FetchRequestServiceFn: func() *automock.FetchRequestService { 1342 svc := &automock.FetchRequestService{} 1343 return svc 1344 }, 1345 ResourceType: resource.Application, 1346 InputID: specID, 1347 Input: *specInputWithFR, 1348 ExpectedErr: testErr, 1349 }, 1350 { 1351 Name: "Fetch Request Creation Error for Application Template Version", 1352 RepositoryFn: func() *automock.SpecRepository { 1353 repo := &automock.SpecRepository{} 1354 repo.On("GetByIDGlobal", ctx, specID).Return(specModel, nil).Once() 1355 return repo 1356 }, 1357 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1358 repo := &automock.FetchRequestRepository{} 1359 repo.On("DeleteByReferenceObjectIDGlobal", ctx, model.APISpecFetchRequestReference, specID).Return(nil).Once() 1360 repo.On("CreateGlobal", ctx, fr).Return(testErr).Once() 1361 return repo 1362 }, 1363 UIDServiceFn: func() *automock.UIDService { 1364 svc := &automock.UIDService{} 1365 svc.On("Generate").Return(specID).Once() 1366 return svc 1367 }, 1368 FetchRequestServiceFn: func() *automock.FetchRequestService { 1369 svc := &automock.FetchRequestService{} 1370 return svc 1371 }, 1372 ResourceType: resource.ApplicationTemplateVersion, 1373 InputID: specID, 1374 Input: *specInputWithFR, 1375 ExpectedErr: testErr, 1376 }, 1377 { 1378 Name: "Get Error for Application", 1379 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1380 repo := &automock.FetchRequestRepository{} 1381 return repo 1382 }, 1383 UIDServiceFn: func() *automock.UIDService { 1384 svc := &automock.UIDService{} 1385 return svc 1386 }, 1387 RepositoryFn: func() *automock.SpecRepository { 1388 repo := &automock.SpecRepository{} 1389 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(nil, testErr).Once() 1390 return repo 1391 }, 1392 FetchRequestServiceFn: func() *automock.FetchRequestService { 1393 svc := &automock.FetchRequestService{} 1394 return svc 1395 }, 1396 ResourceType: resource.Application, 1397 InputID: specID, 1398 Input: *specInputWithFR, 1399 ExpectedErr: testErr, 1400 }, 1401 { 1402 Name: "Get Error for Application Template Version", 1403 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1404 repo := &automock.FetchRequestRepository{} 1405 return repo 1406 }, 1407 UIDServiceFn: func() *automock.UIDService { 1408 svc := &automock.UIDService{} 1409 return svc 1410 }, 1411 RepositoryFn: func() *automock.SpecRepository { 1412 repo := &automock.SpecRepository{} 1413 repo.On("GetByIDGlobal", ctx, specID).Return(nil, testErr).Once() 1414 return repo 1415 }, 1416 FetchRequestServiceFn: func() *automock.FetchRequestService { 1417 svc := &automock.FetchRequestService{} 1418 return svc 1419 }, 1420 ResourceType: resource.ApplicationTemplateVersion, 1421 InputID: specID, 1422 Input: *specInputWithFR, 1423 ExpectedErr: testErr, 1424 }, 1425 } 1426 1427 for _, testCase := range testCases { 1428 t.Run(testCase.Name, func(t *testing.T) { 1429 // GIVEN 1430 repo := testCase.RepositoryFn() 1431 fetchRequestRepo := testCase.FetchRequestRepoFn() 1432 uidSvc := testCase.UIDServiceFn() 1433 fetchRequestSvc := testCase.FetchRequestServiceFn() 1434 1435 svc := spec.NewService(repo, fetchRequestRepo, uidSvc, fetchRequestSvc) 1436 svc.SetTimestampGen(func() time.Time { return timestamp }) 1437 1438 // WHEN 1439 err := svc.UpdateByReferenceObjectID(ctx, testCase.InputID, testCase.Input, testCase.ResourceType, model.APISpecReference, apiID) 1440 1441 // then 1442 if testCase.ExpectedErr == nil { 1443 require.NoError(t, err) 1444 } else { 1445 require.Error(t, err) 1446 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 1447 } 1448 1449 repo.AssertExpectations(t) 1450 fetchRequestRepo.AssertExpectations(t) 1451 uidSvc.AssertExpectations(t) 1452 }) 1453 } 1454 t.Run("Error when tenant not in context", func(t *testing.T) { 1455 svc := spec.NewService(nil, nil, nil, nil) 1456 // WHEN 1457 err := svc.UpdateByReferenceObjectID(context.TODO(), "", model.SpecInput{}, resource.Application, model.APISpecReference, apiID) 1458 // THEN 1459 require.Error(t, err) 1460 assert.Contains(t, err.Error(), "cannot read tenant from context") 1461 }) 1462 } 1463 1464 func TestService_UpdateSpecOnly(t *testing.T) { 1465 testSpec := &model.Spec{} 1466 1467 testCases := []struct { 1468 Name string 1469 Context context.Context 1470 SpecRepoMock *automock.SpecRepository 1471 ExpectedResult *model.Spec 1472 ExpectedError error 1473 }{ 1474 { 1475 Name: "Success", 1476 Context: tnt.SaveToContext(context.TODO(), tenantID, tenantID), 1477 SpecRepoMock: func() *automock.SpecRepository { 1478 specRepositoryMock := automock.SpecRepository{} 1479 specRepositoryMock.On("Update", mock.Anything, tenantID, testSpec).Return(nil).Once() 1480 return &specRepositoryMock 1481 }(), 1482 ExpectedError: nil, 1483 }, 1484 { 1485 Name: "Fails when tenant is missing in context", 1486 Context: context.TODO(), 1487 SpecRepoMock: &automock.SpecRepository{}, 1488 ExpectedError: apperrors.NewCannotReadTenantError(), 1489 }, 1490 { 1491 Name: "Fails when repo update fails", 1492 Context: tnt.SaveToContext(context.TODO(), tenantID, tenantID), 1493 SpecRepoMock: func() *automock.SpecRepository { 1494 specRepositoryMock := automock.SpecRepository{} 1495 specRepositoryMock.On("Update", mock.Anything, tenantID, testSpec).Return(testErr).Once() 1496 return &specRepositoryMock 1497 }(), 1498 ExpectedError: testErr, 1499 }, 1500 } 1501 1502 for _, testCase := range testCases { 1503 t.Run(testCase.Name, func(t *testing.T) { 1504 repo := testCase.SpecRepoMock 1505 svc := spec.NewService(repo, nil, nil, nil) 1506 1507 err := svc.UpdateSpecOnly(testCase.Context, *testSpec) 1508 if testCase.ExpectedError != nil { 1509 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 1510 } 1511 1512 repo.AssertExpectations(t) 1513 }) 1514 } 1515 } 1516 1517 func TestService_UpdateSpecOnlyGlobal(t *testing.T) { 1518 testSpec := &model.Spec{} 1519 1520 testCases := []struct { 1521 Name string 1522 SpecRepoMock *automock.SpecRepository 1523 ExpectedResult *model.Spec 1524 ExpectedError error 1525 }{ 1526 { 1527 Name: "Success", 1528 SpecRepoMock: func() *automock.SpecRepository { 1529 specRepositoryMock := automock.SpecRepository{} 1530 specRepositoryMock.On("UpdateGlobal", mock.Anything, testSpec).Return(nil).Once() 1531 return &specRepositoryMock 1532 }(), 1533 ExpectedError: nil, 1534 }, 1535 { 1536 Name: "Fails when repo update fails", 1537 SpecRepoMock: func() *automock.SpecRepository { 1538 specRepositoryMock := automock.SpecRepository{} 1539 specRepositoryMock.On("UpdateGlobal", mock.Anything, testSpec).Return(testErr).Once() 1540 return &specRepositoryMock 1541 }(), 1542 ExpectedError: testErr, 1543 }, 1544 } 1545 1546 for _, testCase := range testCases { 1547 t.Run(testCase.Name, func(t *testing.T) { 1548 repo := testCase.SpecRepoMock 1549 svc := spec.NewService(repo, nil, nil, nil) 1550 1551 err := svc.UpdateSpecOnlyGlobal(context.TODO(), *testSpec) 1552 if testCase.ExpectedError != nil { 1553 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 1554 } 1555 1556 repo.AssertExpectations(t) 1557 }) 1558 } 1559 } 1560 1561 func TestService_Delete(t *testing.T) { 1562 // GIVEN 1563 testErr := errors.New("Test error") 1564 1565 id := "foo" 1566 1567 ctx := context.TODO() 1568 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 1569 1570 var testCases = []struct { 1571 Name string 1572 RepositoryFn func() *automock.SpecRepository 1573 InputID string 1574 ExpectedErr error 1575 }{ 1576 { 1577 Name: "Success", 1578 RepositoryFn: func() *automock.SpecRepository { 1579 repo := &automock.SpecRepository{} 1580 repo.On("Delete", ctx, tenant, id, model.APISpecReference).Return(nil).Once() 1581 return repo 1582 }, 1583 InputID: id, 1584 ExpectedErr: nil, 1585 }, 1586 { 1587 Name: "Delete Error", 1588 RepositoryFn: func() *automock.SpecRepository { 1589 repo := &automock.SpecRepository{} 1590 repo.On("Delete", ctx, tenant, id, model.APISpecReference).Return(testErr).Once() 1591 return repo 1592 }, 1593 InputID: id, 1594 ExpectedErr: testErr, 1595 }, 1596 } 1597 for _, testCase := range testCases { 1598 t.Run(testCase.Name, func(t *testing.T) { 1599 // GIVEN 1600 repo := testCase.RepositoryFn() 1601 1602 svc := spec.NewService(repo, nil, nil, nil) 1603 1604 // WHEN 1605 err := svc.Delete(ctx, testCase.InputID, model.APISpecReference) 1606 1607 // then 1608 if testCase.ExpectedErr == nil { 1609 require.NoError(t, err) 1610 } else { 1611 require.Error(t, err) 1612 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 1613 } 1614 1615 repo.AssertExpectations(t) 1616 }) 1617 } 1618 1619 t.Run("Error when tenant not in context", func(t *testing.T) { 1620 svc := spec.NewService(nil, nil, nil, nil) 1621 // WHEN 1622 err := svc.Delete(context.TODO(), "", model.APISpecReference) 1623 // THEN 1624 require.Error(t, err) 1625 assert.Contains(t, err.Error(), "cannot read tenant from context") 1626 }) 1627 } 1628 1629 func TestService_RefetchSpec(t *testing.T) { 1630 // GIVEN 1631 testErr := errors.New("Test error") 1632 1633 ctx := context.TODO() 1634 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 1635 1636 dataBytes := "data" 1637 modelSpec := &model.Spec{ 1638 Data: &dataBytes, 1639 } 1640 1641 timestamp := time.Now() 1642 fr := &model.FetchRequest{ 1643 Status: &model.FetchRequestStatus{ 1644 Condition: model.FetchRequestStatusConditionInitial, 1645 Timestamp: timestamp, 1646 }, 1647 } 1648 1649 testCases := []struct { 1650 Name string 1651 RepositoryFn func() *automock.SpecRepository 1652 FetchRequestRepoFn func() *automock.FetchRequestRepository 1653 FetchRequestSvcFn func() *automock.FetchRequestService 1654 ExpectedAPISpec *model.Spec 1655 ExpectedErr error 1656 }{ 1657 { 1658 Name: "Success", 1659 RepositoryFn: func() *automock.SpecRepository { 1660 repo := &automock.SpecRepository{} 1661 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(modelSpec, nil).Once() 1662 repo.On("Update", ctx, tenant, modelSpec).Return(nil).Once() 1663 return repo 1664 }, 1665 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1666 repo := &automock.FetchRequestRepository{} 1667 repo.On("GetByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(nil, nil) 1668 return repo 1669 }, 1670 FetchRequestSvcFn: func() *automock.FetchRequestService { 1671 return &automock.FetchRequestService{} 1672 }, 1673 ExpectedAPISpec: modelSpec, 1674 ExpectedErr: nil, 1675 }, 1676 { 1677 Name: "Success - fetched API Spec", 1678 RepositoryFn: func() *automock.SpecRepository { 1679 repo := &automock.SpecRepository{} 1680 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(modelSpec, nil).Once() 1681 repo.On("Update", ctx, tenant, modelSpec).Return(nil).Once() 1682 return repo 1683 }, 1684 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1685 repo := &automock.FetchRequestRepository{} 1686 repo.On("GetByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(fr, nil) 1687 return repo 1688 }, 1689 FetchRequestSvcFn: func() *automock.FetchRequestService { 1690 svc := &automock.FetchRequestService{} 1691 svc.On("HandleSpec", ctx, fr).Return(&dataBytes) 1692 return svc 1693 }, 1694 ExpectedAPISpec: modelSpec, 1695 ExpectedErr: nil, 1696 }, 1697 { 1698 Name: "Get from repository error", 1699 RepositoryFn: func() *automock.SpecRepository { 1700 repo := &automock.SpecRepository{} 1701 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(nil, testErr).Once() 1702 return repo 1703 }, 1704 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1705 return &automock.FetchRequestRepository{} 1706 }, 1707 FetchRequestSvcFn: func() *automock.FetchRequestService { 1708 return &automock.FetchRequestService{} 1709 }, 1710 ExpectedAPISpec: nil, 1711 ExpectedErr: testErr, 1712 }, 1713 { 1714 Name: "Get fetch request error", 1715 RepositoryFn: func() *automock.SpecRepository { 1716 repo := &automock.SpecRepository{} 1717 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(modelSpec, nil).Once() 1718 return repo 1719 }, 1720 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1721 repo := &automock.FetchRequestRepository{} 1722 repo.On("GetByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(nil, testErr) 1723 return repo 1724 }, 1725 FetchRequestSvcFn: func() *automock.FetchRequestService { 1726 return &automock.FetchRequestService{} 1727 }, 1728 ExpectedAPISpec: nil, 1729 ExpectedErr: errors.Wrapf(testErr, "while getting FetchRequest for Specification with id %q", specID), 1730 }, 1731 { 1732 Name: "Error when updating API Definition failed", 1733 RepositoryFn: func() *automock.SpecRepository { 1734 repo := &automock.SpecRepository{} 1735 repo.On("GetByID", ctx, tenant, specID, model.APISpecReference).Return(modelSpec, nil).Once() 1736 repo.On("Update", ctx, tenant, modelSpec).Return(testErr).Once() 1737 return repo 1738 }, 1739 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1740 repo := &automock.FetchRequestRepository{} 1741 repo.On("GetByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(nil, nil) 1742 return repo 1743 }, 1744 FetchRequestSvcFn: func() *automock.FetchRequestService { 1745 svc := &automock.FetchRequestService{} 1746 return svc 1747 }, 1748 ExpectedAPISpec: nil, 1749 ExpectedErr: errors.Wrapf(testErr, "while updating Specification with id %q", specID), 1750 }, 1751 } 1752 1753 for _, testCase := range testCases { 1754 t.Run(testCase.Name, func(t *testing.T) { 1755 // GIVEN 1756 repo := testCase.RepositoryFn() 1757 frRepo := testCase.FetchRequestRepoFn() 1758 frSvc := testCase.FetchRequestSvcFn() 1759 1760 svc := spec.NewService(repo, frRepo, nil, frSvc) 1761 1762 // WHEN 1763 result, err := svc.RefetchSpec(ctx, specID, model.APISpecReference) 1764 1765 // then 1766 assert.Equal(t, testCase.ExpectedAPISpec, result) 1767 1768 if testCase.ExpectedErr != nil { 1769 require.Error(t, err) 1770 assert.Equal(t, testCase.ExpectedErr.Error(), err.Error()) 1771 } else { 1772 assert.NoError(t, err) 1773 } 1774 repo.AssertExpectations(t) 1775 }) 1776 } 1777 t.Run("Error when tenant not in context", func(t *testing.T) { 1778 svc := spec.NewService(nil, nil, nil, nil) 1779 // WHEN 1780 _, err := svc.RefetchSpec(context.TODO(), "", model.APISpecReference) 1781 // THEN 1782 require.Error(t, err) 1783 assert.Contains(t, err.Error(), "cannot read tenant from context") 1784 }) 1785 } 1786 1787 func TestService_GetFetchRequest(t *testing.T) { 1788 // GIVEN 1789 ctx := context.TODO() 1790 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 1791 1792 testErr := errors.New("Test error") 1793 1794 frURL := "foo.bar" 1795 1796 timestamp := time.Now() 1797 fr := &model.FetchRequest{ 1798 URL: frURL, 1799 Status: &model.FetchRequestStatus{ 1800 Condition: model.FetchRequestStatusConditionInitial, 1801 Timestamp: timestamp, 1802 }, 1803 } 1804 1805 testCases := []struct { 1806 Name string 1807 RepositoryFn func() *automock.SpecRepository 1808 FetchRequestRepoFn func() *automock.FetchRequestRepository 1809 InputAPIDefID string 1810 ExpectedFetchRequest *model.FetchRequest 1811 ExpectedErrMessage string 1812 }{ 1813 { 1814 Name: "Success", 1815 RepositoryFn: func() *automock.SpecRepository { 1816 repo := &automock.SpecRepository{} 1817 repo.On("Exists", ctx, tenant, specID, model.APISpecReference).Return(true, nil).Once() 1818 return repo 1819 }, 1820 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1821 repo := &automock.FetchRequestRepository{} 1822 repo.On("GetByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(fr, nil).Once() 1823 return repo 1824 }, 1825 InputAPIDefID: specID, 1826 ExpectedFetchRequest: fr, 1827 ExpectedErrMessage: "", 1828 }, 1829 { 1830 Name: "Error - Spec Not Exist", 1831 RepositoryFn: func() *automock.SpecRepository { 1832 repo := &automock.SpecRepository{} 1833 repo.On("Exists", ctx, tenant, specID, model.APISpecReference).Return(false, nil).Once() 1834 return repo 1835 }, 1836 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1837 return &automock.FetchRequestRepository{} 1838 }, 1839 InputAPIDefID: specID, 1840 ExpectedFetchRequest: nil, 1841 ExpectedErrMessage: fmt.Sprintf("specification with id %q doesn't exist", specID), 1842 }, 1843 { 1844 Name: "Success - Not Found", 1845 RepositoryFn: func() *automock.SpecRepository { 1846 repo := &automock.SpecRepository{} 1847 repo.On("Exists", ctx, tenant, specID, model.APISpecReference).Return(true, nil).Once() 1848 return repo 1849 }, 1850 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1851 repo := &automock.FetchRequestRepository{} 1852 repo.On("GetByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(nil, apperrors.NewNotFoundError(resource.API, "")).Once() 1853 return repo 1854 }, 1855 InputAPIDefID: specID, 1856 ExpectedFetchRequest: nil, 1857 ExpectedErrMessage: fmt.Sprintf("while getting FetchRequest by Specification with id %q", specID), 1858 }, 1859 { 1860 Name: "Error - Get FetchRequest", 1861 RepositoryFn: func() *automock.SpecRepository { 1862 repo := &automock.SpecRepository{} 1863 repo.On("Exists", ctx, tenant, specID, model.APISpecReference).Return(true, nil).Once() 1864 return repo 1865 }, 1866 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1867 repo := &automock.FetchRequestRepository{} 1868 repo.On("GetByReferenceObjectID", ctx, tenant, model.APISpecFetchRequestReference, specID).Return(nil, testErr).Once() 1869 return repo 1870 }, 1871 InputAPIDefID: specID, 1872 ExpectedFetchRequest: nil, 1873 ExpectedErrMessage: testErr.Error(), 1874 }, 1875 { 1876 Name: "Error - Spec doesn't exist", 1877 RepositoryFn: func() *automock.SpecRepository { 1878 repo := &automock.SpecRepository{} 1879 repo.On("Exists", ctx, tenant, specID, model.APISpecReference).Return(false, testErr).Once() 1880 1881 return repo 1882 }, 1883 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 1884 repo := &automock.FetchRequestRepository{} 1885 return repo 1886 }, 1887 InputAPIDefID: specID, 1888 ExpectedErrMessage: testErr.Error(), 1889 }, 1890 } 1891 1892 for _, testCase := range testCases { 1893 t.Run(testCase.Name, func(t *testing.T) { 1894 repo := testCase.RepositoryFn() 1895 fetchRequestRepo := testCase.FetchRequestRepoFn() 1896 svc := spec.NewService(repo, fetchRequestRepo, nil, nil) 1897 1898 // WHEN 1899 l, err := svc.GetFetchRequest(ctx, testCase.InputAPIDefID, model.APISpecReference) 1900 1901 // then 1902 if testCase.ExpectedErrMessage == "" { 1903 require.NoError(t, err) 1904 assert.Equal(t, l, testCase.ExpectedFetchRequest) 1905 } else { 1906 require.Error(t, err) 1907 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 1908 } 1909 1910 repo.AssertExpectations(t) 1911 fetchRequestRepo.AssertExpectations(t) 1912 }) 1913 } 1914 t.Run("Returns error on loading tenant", func(t *testing.T) { 1915 svc := spec.NewService(nil, nil, nil, nil) 1916 // WHEN 1917 _, err := svc.GetFetchRequest(context.TODO(), "dd", model.APISpecReference) 1918 assert.True(t, apperrors.IsCannotReadTenant(err)) 1919 }) 1920 } 1921 1922 func TestService_ListFetchRequestsByReferenceObjectIDs(t *testing.T) { 1923 // GIVEN 1924 testErr := errors.New("Test error") 1925 frURL := "foo.bar" 1926 firstFRID := "frID" 1927 secondFRID := "frID2" 1928 firstSpecID := "specID" 1929 secondSpecID := "specID2" 1930 specIDs := []string{firstSpecID, secondSpecID} 1931 timestamp := time.Now() 1932 1933 firstFetchRequest := &model.FetchRequest{ 1934 ID: firstFRID, 1935 URL: frURL, 1936 Status: &model.FetchRequestStatus{ 1937 Condition: model.FetchRequestStatusConditionInitial, 1938 Timestamp: timestamp, 1939 }, 1940 } 1941 1942 secondFetchRequest := &model.FetchRequest{ 1943 ID: secondFRID, 1944 URL: frURL, 1945 Status: &model.FetchRequestStatus{ 1946 Condition: model.FetchRequestStatusConditionInitial, 1947 Timestamp: timestamp, 1948 }, 1949 } 1950 fetchRequests := []*model.FetchRequest{firstFetchRequest, secondFetchRequest} 1951 1952 ctx := context.TODO() 1953 ctx = tnt.SaveToContext(ctx, tenant, externalTenant) 1954 1955 testCases := []struct { 1956 Name string 1957 RepositoryFn func() *automock.FetchRequestRepository 1958 ExpectedResult []*model.FetchRequest 1959 ExpectedErrMessage string 1960 }{ 1961 { 1962 Name: "Success", 1963 RepositoryFn: func() *automock.FetchRequestRepository { 1964 repo := &automock.FetchRequestRepository{} 1965 repo.On("ListByReferenceObjectIDs", ctx, tenant, model.APISpecFetchRequestReference, specIDs).Return(fetchRequests, nil).Once() 1966 return repo 1967 }, 1968 ExpectedResult: fetchRequests, 1969 }, 1970 { 1971 Name: "Returns error when Fetch Requests listing failed", 1972 RepositoryFn: func() *automock.FetchRequestRepository { 1973 repo := &automock.FetchRequestRepository{} 1974 repo.On("ListByReferenceObjectIDs", ctx, tenant, model.APISpecFetchRequestReference, specIDs).Return(nil, testErr).Once() 1975 return repo 1976 }, 1977 ExpectedResult: nil, 1978 ExpectedErrMessage: testErr.Error(), 1979 }, 1980 } 1981 1982 for _, testCase := range testCases { 1983 t.Run(testCase.Name, func(t *testing.T) { 1984 repo := testCase.RepositoryFn() 1985 1986 svc := spec.NewService(nil, repo, nil, nil) 1987 1988 // WHEN 1989 frs, err := svc.ListFetchRequestsByReferenceObjectIDs(ctx, tenant, specIDs, model.APISpecReference) 1990 1991 // then 1992 if testCase.ExpectedErrMessage == "" { 1993 require.NoError(t, err) 1994 assert.Equal(t, testCase.ExpectedResult, frs) 1995 } else { 1996 require.Error(t, err) 1997 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 1998 } 1999 2000 repo.AssertExpectations(t) 2001 }) 2002 } 2003 } 2004 2005 func TestService_ListFetchRequestsByReferenceObjectIDsGlobal(t *testing.T) { 2006 // GIVEN 2007 testErr := errors.New("Test error") 2008 frURL := "foo.bar" 2009 firstFRID := "frID" 2010 secondFRID := "frID2" 2011 firstSpecID := "specID" 2012 secondSpecID := "specID2" 2013 specIDs := []string{firstSpecID, secondSpecID} 2014 timestamp := time.Now() 2015 2016 firstFetchRequest := &model.FetchRequest{ 2017 ID: firstFRID, 2018 URL: frURL, 2019 Status: &model.FetchRequestStatus{ 2020 Condition: model.FetchRequestStatusConditionInitial, 2021 Timestamp: timestamp, 2022 }, 2023 } 2024 2025 secondFetchRequest := &model.FetchRequest{ 2026 ID: secondFRID, 2027 URL: frURL, 2028 Status: &model.FetchRequestStatus{ 2029 Condition: model.FetchRequestStatusConditionInitial, 2030 Timestamp: timestamp, 2031 }, 2032 } 2033 fetchRequests := []*model.FetchRequest{firstFetchRequest, secondFetchRequest} 2034 2035 ctx := context.TODO() 2036 2037 testCases := []struct { 2038 Name string 2039 RepositoryFn func() *automock.FetchRequestRepository 2040 ExpectedResult []*model.FetchRequest 2041 ExpectedErrMessage string 2042 }{ 2043 { 2044 Name: "Success", 2045 RepositoryFn: func() *automock.FetchRequestRepository { 2046 repo := &automock.FetchRequestRepository{} 2047 repo.On("ListByReferenceObjectIDsGlobal", ctx, model.APISpecFetchRequestReference, specIDs).Return(fetchRequests, nil).Once() 2048 return repo 2049 }, 2050 ExpectedResult: fetchRequests, 2051 }, 2052 { 2053 Name: "Returns error when Fetch Requests listing failed", 2054 RepositoryFn: func() *automock.FetchRequestRepository { 2055 repo := &automock.FetchRequestRepository{} 2056 repo.On("ListByReferenceObjectIDsGlobal", ctx, model.APISpecFetchRequestReference, specIDs).Return(nil, testErr).Once() 2057 return repo 2058 }, 2059 ExpectedResult: nil, 2060 ExpectedErrMessage: testErr.Error(), 2061 }, 2062 } 2063 2064 for _, testCase := range testCases { 2065 t.Run(testCase.Name, func(t *testing.T) { 2066 repo := testCase.RepositoryFn() 2067 2068 svc := spec.NewService(nil, repo, nil, nil) 2069 2070 // WHEN 2071 frs, err := svc.ListFetchRequestsByReferenceObjectIDsGlobal(ctx, specIDs, model.APISpecReference) 2072 2073 // then 2074 if testCase.ExpectedErrMessage == "" { 2075 require.NoError(t, err) 2076 assert.Equal(t, testCase.ExpectedResult, frs) 2077 } else { 2078 require.Error(t, err) 2079 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 2080 } 2081 2082 repo.AssertExpectations(t) 2083 }) 2084 } 2085 } 2086 2087 func fixUIDService() *automock.UIDService { 2088 svc := &automock.UIDService{} 2089 svc.On("Generate").Return(specID).Once() 2090 return svc 2091 }