github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/document/service_test.go (about) 1 package document_test 2 3 import ( 4 "context" 5 "errors" 6 "testing" 7 "time" 8 9 "github.com/kyma-incubator/compass/components/director/pkg/resource" 10 11 "github.com/kyma-incubator/compass/components/director/internal/domain/document" 12 "github.com/kyma-incubator/compass/components/director/internal/domain/document/automock" 13 "github.com/kyma-incubator/compass/components/director/internal/domain/tenant" 14 "github.com/kyma-incubator/compass/components/director/internal/model" 15 "github.com/kyma-incubator/compass/components/director/pkg/pagination" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 ) 19 20 func TestService_Get(t *testing.T) { 21 // GIVEN 22 testErr := errors.New("Test error") 23 24 id := "foo" 25 26 documentModel := fixModelDocumentForApp("1", id) 27 tnt := givenTenant() 28 externalTnt := "external-tnt" 29 30 ctx := context.TODO() 31 ctx = tenant.SaveToContext(ctx, tnt, externalTnt) 32 33 testCases := []struct { 34 Name string 35 RepositoryFn func() *automock.DocumentRepository 36 Input model.DocumentInput 37 InputID string 38 ExpectedDocument *model.Document 39 ExpectedErrMessage string 40 }{ 41 { 42 Name: "Success", 43 RepositoryFn: func() *automock.DocumentRepository { 44 repo := &automock.DocumentRepository{} 45 repo.On("GetByID", ctx, tnt, id).Return(documentModel, nil).Once() 46 return repo 47 }, 48 InputID: id, 49 ExpectedDocument: documentModel, 50 ExpectedErrMessage: "", 51 }, 52 { 53 Name: "Returns error when document retrieval failed", 54 RepositoryFn: func() *automock.DocumentRepository { 55 repo := &automock.DocumentRepository{} 56 repo.On("GetByID", ctx, tnt, id).Return(nil, testErr).Once() 57 return repo 58 }, 59 InputID: id, 60 ExpectedDocument: documentModel, 61 ExpectedErrMessage: testErr.Error(), 62 }, 63 } 64 65 for _, testCase := range testCases { 66 t.Run(testCase.Name, func(t *testing.T) { 67 repo := testCase.RepositoryFn() 68 69 svc := document.NewService(repo, nil, nil) 70 71 // WHEN 72 doc, err := svc.Get(ctx, testCase.InputID) 73 74 // then 75 if testCase.ExpectedErrMessage == "" { 76 require.NoError(t, err) 77 assert.Equal(t, testCase.ExpectedDocument, doc) 78 } else { 79 require.Error(t, err) 80 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 81 } 82 83 repo.AssertExpectations(t) 84 }) 85 } 86 } 87 88 func TestService_GetForBundle(t *testing.T) { 89 // GIVEN 90 testErr := errors.New("Test error") 91 id := "foo" 92 bndlID := bndlID() 93 tenantID := "bar" 94 externalTenantID := "external-tenant" 95 96 bundleID := "test" 97 doc := fixModelDocumentForApp(id, bndlID) 98 99 ctx := context.TODO() 100 ctx = tenant.SaveToContext(ctx, tenantID, externalTenantID) 101 102 testCases := []struct { 103 Name string 104 RepositoryFn func() *automock.DocumentRepository 105 Input model.DocumentInput 106 InputID string 107 BundleID string 108 ExpectedDocument *model.Document 109 ExpectedErrMessage string 110 }{ 111 { 112 Name: "Success", 113 RepositoryFn: func() *automock.DocumentRepository { 114 repo := &automock.DocumentRepository{} 115 repo.On("GetForBundle", ctx, tenantID, id, bundleID).Return(doc, nil).Once() 116 return repo 117 }, 118 InputID: id, 119 BundleID: bundleID, 120 ExpectedDocument: doc, 121 ExpectedErrMessage: "", 122 }, 123 { 124 Name: "Returns error when Event Definition retrieval failed", 125 RepositoryFn: func() *automock.DocumentRepository { 126 repo := &automock.DocumentRepository{} 127 repo.On("GetForBundle", ctx, tenantID, id, bundleID).Return(nil, testErr).Once() 128 return repo 129 }, 130 InputID: id, 131 BundleID: bundleID, 132 ExpectedDocument: doc, 133 ExpectedErrMessage: testErr.Error(), 134 }, 135 } 136 137 for _, testCase := range testCases { 138 t.Run(testCase.Name, func(t *testing.T) { 139 repo := testCase.RepositoryFn() 140 141 svc := document.NewService(repo, nil, nil) 142 143 // WHEN 144 eventAPIDefinition, err := svc.GetForBundle(ctx, testCase.InputID, testCase.BundleID) 145 146 // then 147 if testCase.ExpectedErrMessage == "" { 148 require.NoError(t, err) 149 assert.Equal(t, testCase.ExpectedDocument, eventAPIDefinition) 150 } else { 151 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 152 } 153 154 repo.AssertExpectations(t) 155 }) 156 } 157 t.Run("Error when tenant not in context", func(t *testing.T) { 158 svc := document.NewService(nil, nil, nil) 159 // WHEN 160 _, err := svc.GetForBundle(context.TODO(), "", "") 161 // THEN 162 require.Error(t, err) 163 assert.Contains(t, err.Error(), "cannot read tenant from context") 164 }) 165 } 166 167 func TestService_CreateToBundle(t *testing.T) { 168 // GIVEN 169 testErr := errors.New("Test error") 170 171 tnt := "tenant" 172 externalTnt := "external-tenant" 173 174 ctx := context.TODO() 175 ctx = tenant.SaveToContext(ctx, tnt, externalTnt) 176 177 id := "foo" 178 bundleID := "foo" 179 frURL := "foo.bar" 180 frID := "fr-id" 181 timestamp := time.Now() 182 modelInput := fixModelDocumentInputWithFetchRequest(frURL) 183 modelAppDoc := modelInput.ToDocumentWithinBundle(id, bundleID, resource.Application, appID) 184 modelAppTemplateVersionDoc := modelInput.ToDocumentWithinBundle(id, bundleID, resource.ApplicationTemplateVersion, appTemplateVersionID) 185 186 testCases := []struct { 187 Name string 188 RepositoryFn func() *automock.DocumentRepository 189 FetchRequestRepoFn func() *automock.FetchRequestRepository 190 UIDServiceFn func() *automock.UIDService 191 Input model.DocumentInput 192 ResourceType resource.Type 193 ResourceID string 194 ExpectedErr error 195 }{ 196 { 197 Name: "Success for Application", 198 RepositoryFn: func() *automock.DocumentRepository { 199 repo := &automock.DocumentRepository{} 200 repo.On("Create", ctx, tnt, modelAppDoc).Return(nil).Once() 201 return repo 202 }, 203 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 204 repo := &automock.FetchRequestRepository{} 205 repo.On("Create", ctx, tnt, fixModelFetchRequest(frID, frURL, timestamp)).Return(nil).Once() 206 return repo 207 }, 208 UIDServiceFn: func() *automock.UIDService { 209 svc := &automock.UIDService{} 210 svc.On("Generate").Return(id).Once() 211 svc.On("Generate").Return(frID).Once() 212 return svc 213 }, 214 Input: *modelInput, 215 ResourceType: resource.Application, 216 ResourceID: appID, 217 ExpectedErr: nil, 218 }, 219 { 220 Name: "Success for Application Template Version", 221 RepositoryFn: func() *automock.DocumentRepository { 222 repo := &automock.DocumentRepository{} 223 repo.On("CreateGlobal", ctx, modelAppTemplateVersionDoc).Return(nil).Once() 224 return repo 225 }, 226 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 227 repo := &automock.FetchRequestRepository{} 228 repo.On("CreateGlobal", ctx, fixModelFetchRequest(frID, frURL, timestamp)).Return(nil).Once() 229 return repo 230 }, 231 UIDServiceFn: func() *automock.UIDService { 232 svc := &automock.UIDService{} 233 svc.On("Generate").Return(id).Once() 234 svc.On("Generate").Return(frID).Once() 235 return svc 236 }, 237 Input: *modelInput, 238 ResourceType: resource.ApplicationTemplateVersion, 239 ResourceID: appTemplateVersionID, 240 ExpectedErr: nil, 241 }, 242 { 243 Name: "Returns error when document creation failed for Application", 244 RepositoryFn: func() *automock.DocumentRepository { 245 repo := &automock.DocumentRepository{} 246 repo.On("Create", ctx, tnt, modelAppDoc).Return(testErr).Once() 247 return repo 248 }, 249 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 250 repo := &automock.FetchRequestRepository{} 251 return repo 252 }, 253 UIDServiceFn: func() *automock.UIDService { 254 svc := &automock.UIDService{} 255 svc.On("Generate").Return(id).Once() 256 return svc 257 }, 258 Input: *modelInput, 259 ResourceType: resource.Application, 260 ResourceID: appID, 261 ExpectedErr: testErr, 262 }, 263 { 264 Name: "Returns error when document creation failed for Application Template Version", 265 RepositoryFn: func() *automock.DocumentRepository { 266 repo := &automock.DocumentRepository{} 267 repo.On("CreateGlobal", ctx, modelAppTemplateVersionDoc).Return(testErr).Once() 268 return repo 269 }, 270 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 271 repo := &automock.FetchRequestRepository{} 272 return repo 273 }, 274 UIDServiceFn: func() *automock.UIDService { 275 svc := &automock.UIDService{} 276 svc.On("Generate").Return(id).Once() 277 return svc 278 }, 279 Input: *modelInput, 280 ResourceType: resource.ApplicationTemplateVersion, 281 ResourceID: appTemplateVersionID, 282 ExpectedErr: testErr, 283 }, 284 { 285 Name: "Error - Fetch Request Creation for Application", 286 RepositoryFn: func() *automock.DocumentRepository { 287 repo := &automock.DocumentRepository{} 288 repo.On("Create", ctx, tnt, modelAppDoc).Return(nil).Once() 289 return repo 290 }, 291 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 292 repo := &automock.FetchRequestRepository{} 293 repo.On("Create", ctx, tnt, fixModelFetchRequest(frID, frURL, timestamp)).Return(testErr).Once() 294 return repo 295 }, 296 UIDServiceFn: func() *automock.UIDService { 297 svc := &automock.UIDService{} 298 svc.On("Generate").Return(id).Once() 299 svc.On("Generate").Return(frID).Once() 300 return svc 301 }, 302 Input: *modelInput, 303 ResourceType: resource.Application, 304 ResourceID: appID, 305 ExpectedErr: testErr, 306 }, 307 { 308 Name: "Error - Fetch Request Creation for Application Template Version", 309 RepositoryFn: func() *automock.DocumentRepository { 310 repo := &automock.DocumentRepository{} 311 repo.On("CreateGlobal", ctx, modelAppTemplateVersionDoc).Return(nil).Once() 312 return repo 313 }, 314 FetchRequestRepoFn: func() *automock.FetchRequestRepository { 315 repo := &automock.FetchRequestRepository{} 316 repo.On("CreateGlobal", ctx, fixModelFetchRequest(frID, frURL, timestamp)).Return(testErr).Once() 317 return repo 318 }, 319 UIDServiceFn: func() *automock.UIDService { 320 svc := &automock.UIDService{} 321 svc.On("Generate").Return(id).Once() 322 svc.On("Generate").Return(frID).Once() 323 return svc 324 }, 325 Input: *modelInput, 326 ResourceType: resource.ApplicationTemplateVersion, 327 ResourceID: appTemplateVersionID, 328 ExpectedErr: testErr, 329 }, 330 } 331 332 for _, testCase := range testCases { 333 t.Run(testCase.Name, func(t *testing.T) { 334 repo := testCase.RepositoryFn() 335 idSvc := testCase.UIDServiceFn() 336 fetchRequestRepo := testCase.FetchRequestRepoFn() 337 svc := document.NewService(repo, fetchRequestRepo, idSvc) 338 svc.SetTimestampGen(func() time.Time { return timestamp }) 339 340 // WHEN 341 result, err := svc.CreateInBundle(ctx, testCase.ResourceType, testCase.ResourceID, bundleID, testCase.Input) 342 343 // then 344 assert.IsType(t, "string", result) 345 if testCase.ExpectedErr == nil { 346 require.NoError(t, err) 347 } else { 348 require.Error(t, err) 349 assert.Contains(t, err.Error(), testCase.ExpectedErr.Error()) 350 } 351 352 repo.AssertExpectations(t) 353 idSvc.AssertExpectations(t) 354 fetchRequestRepo.AssertExpectations(t) 355 }) 356 } 357 358 t.Run("Returns error on loading tenant", func(t *testing.T) { 359 svc := document.NewService(nil, nil, fixUIDSvc()) 360 // WHEN 361 _, err := svc.CreateInBundle(context.TODO(), resource.Application, "appID", "bndlID", model.DocumentInput{}) 362 assert.Contains(t, err.Error(), "cannot read tenant from context") 363 }) 364 } 365 func TestService_Delete(t *testing.T) { 366 // GIVEN 367 testErr := errors.New("Test error") 368 369 id := "bar" 370 371 tnt := givenTenant() 372 externalTnt := "external-tnt" 373 374 ctx := context.TODO() 375 ctx = tenant.SaveToContext(ctx, tnt, externalTnt) 376 377 testCases := []struct { 378 Name string 379 RepositoryFn func() *automock.DocumentRepository 380 Input model.DocumentInput 381 InputID string 382 ExpectedErrMessage string 383 }{ 384 { 385 Name: "Success", 386 RepositoryFn: func() *automock.DocumentRepository { 387 repo := &automock.DocumentRepository{} 388 repo.On("Delete", ctx, tnt, id).Return(nil).Once() 389 return repo 390 }, 391 InputID: id, 392 ExpectedErrMessage: "", 393 }, 394 { 395 Name: "Returns error when document deletion failed", 396 RepositoryFn: func() *automock.DocumentRepository { 397 repo := &automock.DocumentRepository{} 398 repo.On("Delete", ctx, tnt, id).Return(testErr).Once() 399 return repo 400 }, 401 InputID: id, 402 ExpectedErrMessage: testErr.Error(), 403 }, 404 } 405 406 for _, testCase := range testCases { 407 t.Run(testCase.Name, func(t *testing.T) { 408 repo := testCase.RepositoryFn() 409 410 svc := document.NewService(repo, nil, nil) 411 412 // WHEN 413 err := svc.Delete(ctx, testCase.InputID) 414 415 // then 416 if testCase.ExpectedErrMessage == "" { 417 require.NoError(t, err) 418 } else { 419 require.Error(t, err) 420 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 421 } 422 423 repo.AssertExpectations(t) 424 }) 425 } 426 } 427 428 func TestService_ListByBundleIDs(t *testing.T) { 429 // GIVEN 430 testErr := errors.New("test error") 431 432 tnt := "tenant" 433 externalTnt := "external-tenant" 434 firstDocID := "foo" 435 secondDocID := "foo2" 436 firstBundleID := "bar" 437 secondBundleID := "bar2" 438 bundleIDs := []string{firstBundleID, secondBundleID} 439 440 docFirstBundle := fixModelDocumentForApp(firstDocID, firstBundleID) 441 docSecondBundle := fixModelDocumentForApp(secondDocID, secondBundleID) 442 443 docsFirstBundle := []*model.Document{docFirstBundle} 444 docsSecondBundle := []*model.Document{docSecondBundle} 445 446 docPageFirstBundle := &model.DocumentPage{ 447 Data: docsFirstBundle, 448 TotalCount: len(docsFirstBundle), 449 PageInfo: &pagination.Page{ 450 HasNextPage: false, 451 EndCursor: "end", 452 StartCursor: "start", 453 }, 454 } 455 docPageSecondBundle := &model.DocumentPage{ 456 Data: docsSecondBundle, 457 TotalCount: len(docsSecondBundle), 458 PageInfo: &pagination.Page{ 459 HasNextPage: false, 460 EndCursor: "end", 461 StartCursor: "start", 462 }, 463 } 464 465 docPages := []*model.DocumentPage{docPageFirstBundle, docPageSecondBundle} 466 467 after := "test" 468 469 ctx := context.TODO() 470 ctx = tenant.SaveToContext(ctx, tnt, externalTnt) 471 472 testCases := []struct { 473 Name string 474 PageSize int 475 RepositoryFn func() *automock.DocumentRepository 476 ExpectedResult []*model.DocumentPage 477 ExpectedErrMessage string 478 }{ 479 { 480 Name: "Success", 481 RepositoryFn: func() *automock.DocumentRepository { 482 repo := &automock.DocumentRepository{} 483 repo.On("ListByBundleIDs", ctx, tnt, bundleIDs, 2, after).Return(docPages, nil).Once() 484 return repo 485 }, 486 PageSize: 2, 487 ExpectedResult: docPages, 488 }, 489 { 490 Name: "Return error when page size is less than 1", 491 RepositoryFn: func() *automock.DocumentRepository { 492 repo := &automock.DocumentRepository{} 493 return repo 494 }, 495 PageSize: 0, 496 ExpectedResult: docPages, 497 ExpectedErrMessage: "page size must be between 1 and 200", 498 }, 499 { 500 Name: "Return error when page size is bigger than 200", 501 RepositoryFn: func() *automock.DocumentRepository { 502 repo := &automock.DocumentRepository{} 503 return repo 504 }, 505 PageSize: 201, 506 ExpectedResult: docPages, 507 ExpectedErrMessage: "page size must be between 1 and 200", 508 }, 509 { 510 Name: "Returns error when Documents listing failed", 511 RepositoryFn: func() *automock.DocumentRepository { 512 repo := &automock.DocumentRepository{} 513 repo.On("ListByBundleIDs", ctx, tnt, bundleIDs, 2, after).Return(nil, testErr).Once() 514 return repo 515 }, 516 PageSize: 2, 517 ExpectedResult: nil, 518 ExpectedErrMessage: testErr.Error(), 519 }, 520 } 521 522 for _, testCase := range testCases { 523 t.Run(testCase.Name, func(t *testing.T) { 524 repo := testCase.RepositoryFn() 525 526 svc := document.NewService(repo, nil, nil) 527 528 // WHEN 529 docs, err := svc.ListByBundleIDs(ctx, bundleIDs, testCase.PageSize, after) 530 531 // then 532 if testCase.ExpectedErrMessage == "" { 533 require.NoError(t, err) 534 assert.Equal(t, testCase.ExpectedResult, docs) 535 } else { 536 require.Error(t, err) 537 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 538 } 539 540 repo.AssertExpectations(t) 541 }) 542 } 543 t.Run("Error when tenant not in context", func(t *testing.T) { 544 svc := document.NewService(nil, nil, nil) 545 // WHEN 546 _, err := svc.ListByBundleIDs(context.TODO(), nil, 5, "") 547 // THEN 548 require.Error(t, err) 549 assert.Contains(t, err.Error(), "cannot read tenant from context") 550 }) 551 } 552 553 func TestService_ListFetchRequests(t *testing.T) { 554 // GIVEN 555 tnt := "tenant" 556 externalTnt := "external-tenant" 557 testErr := errors.New("test error") 558 frURL := "foo.bar" 559 firstFRID := "frID" 560 secondFRID := "frID2" 561 firstDocID := "docID" 562 secondDocID := "docID2" 563 docIDs := []string{firstDocID, secondDocID} 564 timestamp := time.Now() 565 566 firstFetchRequest := fixModelFetchRequest(firstFRID, frURL, timestamp) 567 secondFetchRequest := fixModelFetchRequest(secondFRID, frURL, timestamp) 568 fetchRequests := []*model.FetchRequest{firstFetchRequest, secondFetchRequest} 569 570 ctx := context.TODO() 571 ctx = tenant.SaveToContext(ctx, tnt, externalTnt) 572 573 testCases := []struct { 574 Name string 575 RepositoryFn func() *automock.FetchRequestRepository 576 ExpectedResult []*model.FetchRequest 577 ExpectedErrMessage string 578 }{ 579 { 580 Name: "Success", 581 RepositoryFn: func() *automock.FetchRequestRepository { 582 repo := &automock.FetchRequestRepository{} 583 repo.On("ListByReferenceObjectIDs", ctx, tnt, model.DocumentFetchRequestReference, docIDs).Return(fetchRequests, nil).Once() 584 return repo 585 }, 586 ExpectedResult: fetchRequests, 587 }, 588 { 589 Name: "Returns error when Fetch Requests listing failed", 590 RepositoryFn: func() *automock.FetchRequestRepository { 591 repo := &automock.FetchRequestRepository{} 592 repo.On("ListByReferenceObjectIDs", ctx, tnt, model.DocumentFetchRequestReference, docIDs).Return(nil, testErr).Once() 593 return repo 594 }, 595 ExpectedResult: nil, 596 ExpectedErrMessage: testErr.Error(), 597 }, 598 } 599 600 for _, testCase := range testCases { 601 t.Run(testCase.Name, func(t *testing.T) { 602 repo := testCase.RepositoryFn() 603 604 svc := document.NewService(nil, repo, nil) 605 606 // WHEN 607 frs, err := svc.ListFetchRequests(ctx, docIDs) 608 609 // then 610 if testCase.ExpectedErrMessage == "" { 611 require.NoError(t, err) 612 assert.Equal(t, testCase.ExpectedResult, frs) 613 } else { 614 require.Error(t, err) 615 assert.Contains(t, err.Error(), testCase.ExpectedErrMessage) 616 } 617 618 repo.AssertExpectations(t) 619 }) 620 } 621 622 t.Run("Error when tenant not in context", func(t *testing.T) { 623 svc := document.NewService(nil, nil, nil) 624 // WHEN 625 _, err := svc.ListFetchRequests(context.TODO(), nil) 626 // THEN 627 require.Error(t, err) 628 assert.Contains(t, err.Error(), "cannot read tenant from context") 629 }) 630 } 631 632 func fixUIDSvc() *automock.UIDService { 633 svc := &automock.UIDService{} 634 svc.On("Generate").Return(docID) 635 return svc 636 }