github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/runtime_context/resolver_test.go (about) 1 package runtimectx_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/kyma-incubator/compass/components/director/internal/model" 8 "github.com/kyma-incubator/compass/components/director/pkg/graphql" 9 "github.com/kyma-incubator/compass/components/director/pkg/persistence/txtest" 10 11 runtimectx "github.com/kyma-incubator/compass/components/director/internal/domain/runtime_context" 12 "github.com/kyma-incubator/compass/components/director/pkg/consumer" 13 14 "github.com/kyma-incubator/compass/components/director/internal/domain/runtime_context/automock" 15 16 "github.com/kyma-incubator/compass/components/director/pkg/persistence" 17 18 "github.com/stretchr/testify/mock" 19 20 persistenceautomock "github.com/kyma-incubator/compass/components/director/pkg/persistence/automock" 21 "github.com/pkg/errors" 22 "github.com/stretchr/testify/assert" 23 ) 24 25 var contextParam = mock.MatchedBy(func(ctx context.Context) bool { 26 persistenceOp, err := persistence.FromCtx(ctx) 27 return err == nil && persistenceOp != nil 28 }) 29 30 func TestResolver_CreateRuntimeContext(t *testing.T) { 31 // GIVEN 32 id := "foo" 33 key := "key" 34 val := "value" 35 runtimeID := "runtime_id" 36 37 testErr := errors.New("Test error") 38 txGen := txtest.NewTransactionContextGenerator(testErr) 39 40 modelRuntimeContext := &model.RuntimeContext{ 41 ID: id, 42 RuntimeID: runtimeID, 43 Key: key, 44 Value: val, 45 } 46 gqlRuntimeContext := &graphql.RuntimeContext{ 47 ID: id, 48 Key: key, 49 Value: val, 50 } 51 52 gqlInput := graphql.RuntimeContextInput{ 53 Key: key, 54 Value: val, 55 } 56 modelInput := model.RuntimeContextInput{ 57 Key: key, 58 Value: val, 59 RuntimeID: runtimeID, 60 } 61 62 testCases := []struct { 63 Name string 64 TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner) 65 ServiceFn func() *automock.RuntimeContextService 66 ConverterFn func() *automock.RuntimeContextConverter 67 68 Input graphql.RuntimeContextInput 69 ExpectedRuntimeContext *graphql.RuntimeContext 70 ExpectedErr error 71 Consumer *consumer.Consumer 72 }{ 73 { 74 Name: "Success", 75 TransactionerFn: txGen.ThatSucceeds, 76 ServiceFn: func() *automock.RuntimeContextService { 77 svc := &automock.RuntimeContextService{} 78 svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once() 79 svc.On("Create", contextParam, modelInput).Return("foo", nil).Once() 80 return svc 81 }, 82 ConverterFn: func() *automock.RuntimeContextConverter { 83 conv := &automock.RuntimeContextConverter{} 84 conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once() 85 conv.On("ToGraphQL", modelRuntimeContext).Return(gqlRuntimeContext).Once() 86 return conv 87 }, 88 Input: gqlInput, 89 ExpectedRuntimeContext: gqlRuntimeContext, 90 ExpectedErr: nil, 91 }, 92 { 93 Name: "Returns error when transaction begin failed", 94 TransactionerFn: txGen.ThatFailsOnBegin, 95 ServiceFn: func() *automock.RuntimeContextService { 96 svc := &automock.RuntimeContextService{} 97 return svc 98 }, 99 ConverterFn: func() *automock.RuntimeContextConverter { 100 conv := &automock.RuntimeContextConverter{} 101 conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once() 102 return conv 103 }, 104 Input: gqlInput, 105 ExpectedRuntimeContext: nil, 106 ExpectedErr: testErr, 107 }, 108 { 109 Name: "Returns error when runtime context creation failed", 110 TransactionerFn: txGen.ThatDoesntExpectCommit, 111 ServiceFn: func() *automock.RuntimeContextService { 112 svc := &automock.RuntimeContextService{} 113 svc.On("Create", contextParam, modelInput).Return("", testErr).Once() 114 return svc 115 }, 116 ConverterFn: func() *automock.RuntimeContextConverter { 117 conv := &automock.RuntimeContextConverter{} 118 conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once() 119 return conv 120 }, 121 Input: gqlInput, 122 ExpectedRuntimeContext: nil, 123 ExpectedErr: testErr, 124 }, 125 { 126 Name: "Returns error when runtime context retrieval failed", 127 TransactionerFn: txGen.ThatDoesntExpectCommit, 128 ServiceFn: func() *automock.RuntimeContextService { 129 svc := &automock.RuntimeContextService{} 130 svc.On("Create", contextParam, modelInput).Return("foo", nil).Once() 131 svc.On("GetByID", contextParam, "foo").Return(nil, testErr).Once() 132 return svc 133 }, 134 ConverterFn: func() *automock.RuntimeContextConverter { 135 conv := &automock.RuntimeContextConverter{} 136 conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once() 137 return conv 138 }, 139 Input: gqlInput, 140 ExpectedRuntimeContext: nil, 141 ExpectedErr: testErr, 142 }, 143 { 144 Name: "Returns error when transaction commit failed", 145 TransactionerFn: txGen.ThatFailsOnCommit, 146 ServiceFn: func() *automock.RuntimeContextService { 147 svc := &automock.RuntimeContextService{} 148 svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once() 149 svc.On("Create", contextParam, modelInput).Return("foo", nil).Once() 150 return svc 151 }, 152 ConverterFn: func() *automock.RuntimeContextConverter { 153 conv := &automock.RuntimeContextConverter{} 154 conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once() 155 return conv 156 }, 157 Input: gqlInput, 158 ExpectedRuntimeContext: nil, 159 ExpectedErr: testErr, 160 }, 161 } 162 163 for _, testCase := range testCases { 164 t.Run(testCase.Name, func(t *testing.T) { 165 persistTx, transact := testCase.TransactionerFn() 166 svc := testCase.ServiceFn() 167 converter := testCase.ConverterFn() 168 169 resolver := runtimectx.NewResolver(transact, svc, converter) 170 171 c := testCase.Consumer 172 if c == nil { 173 c = &consumer.Consumer{ 174 ConsumerID: runtimeID, 175 ConsumerType: consumer.Runtime, 176 } 177 } 178 ctx := consumer.SaveToContext(context.TODO(), *c) 179 180 // WHEN 181 result, err := resolver.RegisterRuntimeContext(ctx, runtimeID, testCase.Input) 182 183 // then 184 assert.Equal(t, testCase.ExpectedRuntimeContext, result) 185 assert.Equal(t, testCase.ExpectedErr, err) 186 187 mock.AssertExpectationsForObjects(t, svc, converter, transact, persistTx) 188 }) 189 } 190 } 191 192 func TestResolver_UpdateRuntimeContext(t *testing.T) { 193 // GIVEN 194 id := "foo" 195 key := "key" 196 val := "value" 197 runtimeID := "runtime_id" 198 199 testErr := errors.New("Test error") 200 txGen := txtest.NewTransactionContextGenerator(testErr) 201 202 modelRuntimeContext := &model.RuntimeContext{ 203 ID: id, 204 RuntimeID: runtimeID, 205 Key: key, 206 Value: val, 207 } 208 gqlRuntimeContext := &graphql.RuntimeContext{ 209 ID: id, 210 Key: key, 211 Value: val, 212 } 213 214 gqlInput := graphql.RuntimeContextInput{ 215 Key: key, 216 Value: val, 217 } 218 modelInput := model.RuntimeContextInput{ 219 Key: key, 220 Value: val, 221 RuntimeID: runtimeID, 222 } 223 224 testCases := []struct { 225 Name string 226 TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner) 227 ServiceFn func() *automock.RuntimeContextService 228 ConverterFn func() *automock.RuntimeContextConverter 229 RuntimeContextID string 230 Input graphql.RuntimeContextInput 231 ExpectedRuntimeContext *graphql.RuntimeContext 232 ExpectedErr error 233 Consumer *consumer.Consumer 234 }{ 235 { 236 Name: "Success", 237 TransactionerFn: txGen.ThatSucceeds, 238 ServiceFn: func() *automock.RuntimeContextService { 239 svc := &automock.RuntimeContextService{} 240 svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once() 241 svc.On("Update", contextParam, id, modelInput).Return(nil).Once() 242 return svc 243 }, 244 ConverterFn: func() *automock.RuntimeContextConverter { 245 conv := &automock.RuntimeContextConverter{} 246 conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once() 247 conv.On("ToGraphQL", modelRuntimeContext).Return(gqlRuntimeContext).Once() 248 return conv 249 }, 250 RuntimeContextID: id, 251 Input: gqlInput, 252 ExpectedRuntimeContext: gqlRuntimeContext, 253 ExpectedErr: nil, 254 }, 255 { 256 Name: "Returns error when transaction begin failed", 257 TransactionerFn: txGen.ThatFailsOnBegin, 258 ServiceFn: func() *automock.RuntimeContextService { 259 svc := &automock.RuntimeContextService{} 260 return svc 261 }, 262 ConverterFn: func() *automock.RuntimeContextConverter { 263 conv := &automock.RuntimeContextConverter{} 264 conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once() 265 return conv 266 }, 267 Input: gqlInput, 268 ExpectedRuntimeContext: nil, 269 ExpectedErr: testErr, 270 }, 271 { 272 Name: "Returns error when runtime context update failed", 273 TransactionerFn: txGen.ThatDoesntExpectCommit, 274 ServiceFn: func() *automock.RuntimeContextService { 275 svc := &automock.RuntimeContextService{} 276 svc.On("Update", contextParam, id, modelInput).Return(testErr).Once() 277 return svc 278 }, 279 ConverterFn: func() *automock.RuntimeContextConverter { 280 conv := &automock.RuntimeContextConverter{} 281 conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once() 282 return conv 283 }, 284 RuntimeContextID: id, 285 Input: gqlInput, 286 ExpectedRuntimeContext: nil, 287 ExpectedErr: testErr, 288 }, 289 { 290 Name: "Returns error when runtime context retrieval failed", 291 TransactionerFn: txGen.ThatDoesntExpectCommit, 292 ServiceFn: func() *automock.RuntimeContextService { 293 svc := &automock.RuntimeContextService{} 294 svc.On("Update", contextParam, id, modelInput).Return(nil).Once() 295 svc.On("GetByID", contextParam, "foo").Return(nil, testErr).Once() 296 return svc 297 }, 298 ConverterFn: func() *automock.RuntimeContextConverter { 299 conv := &automock.RuntimeContextConverter{} 300 conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once() 301 return conv 302 }, 303 RuntimeContextID: id, 304 Input: gqlInput, 305 ExpectedRuntimeContext: nil, 306 ExpectedErr: testErr, 307 }, 308 { 309 Name: "Returns error when transaction commit failed", 310 TransactionerFn: txGen.ThatFailsOnCommit, 311 ServiceFn: func() *automock.RuntimeContextService { 312 svc := &automock.RuntimeContextService{} 313 svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once() 314 svc.On("Update", contextParam, id, modelInput).Return(nil).Once() 315 return svc 316 }, 317 ConverterFn: func() *automock.RuntimeContextConverter { 318 conv := &automock.RuntimeContextConverter{} 319 conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once() 320 return conv 321 }, 322 RuntimeContextID: id, 323 Input: gqlInput, 324 ExpectedRuntimeContext: nil, 325 ExpectedErr: testErr, 326 }, 327 } 328 329 for _, testCase := range testCases { 330 t.Run(testCase.Name, func(t *testing.T) { 331 persistTx, transact := testCase.TransactionerFn() 332 svc := testCase.ServiceFn() 333 converter := testCase.ConverterFn() 334 335 resolver := runtimectx.NewResolver(transact, svc, converter) 336 337 c := testCase.Consumer 338 if c == nil { 339 c = &consumer.Consumer{ 340 ConsumerID: runtimeID, 341 ConsumerType: consumer.Runtime, 342 } 343 } 344 ctx := consumer.SaveToContext(context.TODO(), *c) 345 346 // WHEN 347 result, err := resolver.UpdateRuntimeContext(ctx, testCase.RuntimeContextID, testCase.Input) 348 349 // then 350 assert.Equal(t, testCase.ExpectedRuntimeContext, result) 351 assert.Equal(t, testCase.ExpectedErr, err) 352 353 mock.AssertExpectationsForObjects(t, svc, converter, transact, persistTx) 354 }) 355 } 356 } 357 358 func TestResolver_DeleteRuntimeContext(t *testing.T) { 359 // GIVEN 360 id := "foo" 361 key := "key" 362 val := "value" 363 runtimeID := "runtime_id" 364 365 testErr := errors.New("Test error") 366 txGen := txtest.NewTransactionContextGenerator(testErr) 367 368 modelRuntimeContext := &model.RuntimeContext{ 369 ID: id, 370 RuntimeID: runtimeID, 371 Key: key, 372 Value: val, 373 } 374 gqlRuntimeContext := &graphql.RuntimeContext{ 375 ID: id, 376 Key: key, 377 Value: val, 378 } 379 380 testCases := []struct { 381 Name string 382 TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner) 383 ServiceFn func() *automock.RuntimeContextService 384 ConverterFn func() *automock.RuntimeContextConverter 385 InputID string 386 ExpectedRuntimeContext *graphql.RuntimeContext 387 ExpectedErr error 388 Consumer *consumer.Consumer 389 }{ 390 { 391 Name: "Success", 392 TransactionerFn: txGen.ThatSucceeds, 393 ServiceFn: func() *automock.RuntimeContextService { 394 svc := &automock.RuntimeContextService{} 395 svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once() 396 svc.On("Delete", contextParam, "foo").Return(nil).Once() 397 return svc 398 }, 399 ConverterFn: func() *automock.RuntimeContextConverter { 400 conv := &automock.RuntimeContextConverter{} 401 conv.On("ToGraphQL", modelRuntimeContext).Return(gqlRuntimeContext).Once() 402 return conv 403 }, 404 InputID: id, 405 ExpectedRuntimeContext: gqlRuntimeContext, 406 ExpectedErr: nil, 407 }, 408 { 409 Name: "Returns error when runtime context deletion failed", 410 TransactionerFn: txGen.ThatDoesntExpectCommit, 411 ServiceFn: func() *automock.RuntimeContextService { 412 svc := &automock.RuntimeContextService{} 413 svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once() 414 svc.On("Delete", contextParam, "foo").Return(testErr).Once() 415 return svc 416 }, 417 ConverterFn: func() *automock.RuntimeContextConverter { 418 conv := &automock.RuntimeContextConverter{} 419 return conv 420 }, 421 InputID: id, 422 ExpectedRuntimeContext: nil, 423 ExpectedErr: testErr, 424 }, 425 { 426 Name: "Returns error when runtime context retrieval failed", 427 TransactionerFn: txGen.ThatDoesntExpectCommit, 428 ServiceFn: func() *automock.RuntimeContextService { 429 svc := &automock.RuntimeContextService{} 430 svc.On("GetByID", contextParam, "foo").Return(nil, testErr).Once() 431 return svc 432 }, 433 ConverterFn: func() *automock.RuntimeContextConverter { 434 conv := &automock.RuntimeContextConverter{} 435 return conv 436 }, 437 InputID: id, 438 ExpectedRuntimeContext: nil, 439 ExpectedErr: testErr, 440 }, 441 { 442 Name: "Returns error when transaction starting failed", 443 TransactionerFn: txGen.ThatFailsOnBegin, 444 ServiceFn: func() *automock.RuntimeContextService { 445 svc := &automock.RuntimeContextService{} 446 return svc 447 }, 448 ConverterFn: func() *automock.RuntimeContextConverter { 449 conv := &automock.RuntimeContextConverter{} 450 return conv 451 }, 452 InputID: id, 453 ExpectedRuntimeContext: nil, 454 ExpectedErr: testErr, 455 }, 456 { 457 Name: "Returns error when transaction commit failed", 458 TransactionerFn: txGen.ThatFailsOnCommit, 459 ServiceFn: func() *automock.RuntimeContextService { 460 svc := &automock.RuntimeContextService{} 461 svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once() 462 svc.On("Delete", contextParam, modelRuntimeContext.ID).Return(nil) 463 return svc 464 }, 465 ConverterFn: func() *automock.RuntimeContextConverter { 466 conv := &automock.RuntimeContextConverter{} 467 return conv 468 }, 469 InputID: id, 470 ExpectedRuntimeContext: nil, 471 ExpectedErr: testErr, 472 }, 473 } 474 475 for _, testCase := range testCases { 476 t.Run(testCase.Name, func(t *testing.T) { 477 persistTx, transact := testCase.TransactionerFn() 478 svc := testCase.ServiceFn() 479 converter := testCase.ConverterFn() 480 481 resolver := runtimectx.NewResolver(transact, svc, converter) 482 483 c := testCase.Consumer 484 if c == nil { 485 c = &consumer.Consumer{ 486 ConsumerID: runtimeID, 487 ConsumerType: consumer.Runtime, 488 } 489 } 490 ctx := consumer.SaveToContext(context.TODO(), *c) 491 492 // WHEN 493 result, err := resolver.DeleteRuntimeContext(ctx, testCase.InputID) 494 495 // then 496 assert.Equal(t, testCase.ExpectedRuntimeContext, result) 497 if testCase.ExpectedErr != nil { 498 assert.EqualError(t, testCase.ExpectedErr, err.Error()) 499 } else { 500 assert.NoError(t, err) 501 } 502 503 mock.AssertExpectationsForObjects(t, svc, converter, transact, persistTx) 504 }) 505 } 506 } 507 508 func TestResolver_Labels(t *testing.T) { 509 // GIVEN 510 id := "foo" 511 labelKey1 := "key1" 512 labelValue1 := "val1" 513 labelKey2 := "key2" 514 labelValue2 := "val2" 515 516 key := "key1" 517 val := "value1" 518 519 testErr := errors.New("Test error") 520 txGen := txtest.NewTransactionContextGenerator(testErr) 521 522 gqlRuntimeContext := &graphql.RuntimeContext{ 523 ID: id, 524 Key: key, 525 Value: val, 526 } 527 528 modelLabels := map[string]*model.Label{ 529 "abc": { 530 ID: "abc", 531 Key: labelKey1, 532 Value: labelValue1, 533 ObjectID: id, 534 ObjectType: model.RuntimeContextLabelableObject, 535 }, 536 "def": { 537 ID: "def", 538 Key: labelKey2, 539 Value: labelValue2, 540 ObjectID: id, 541 ObjectType: model.RuntimeContextLabelableObject, 542 }, 543 } 544 545 gqlLabels := graphql.Labels{ 546 labelKey1: labelValue1, 547 labelKey2: labelValue2, 548 } 549 550 gqlLabels1 := graphql.Labels{ 551 labelKey1: labelValue1, 552 } 553 554 testCases := []struct { 555 Name string 556 TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner) 557 ServiceFn func() *automock.RuntimeContextService 558 InputRuntimeContext *graphql.RuntimeContext 559 InputKey *string 560 ExpectedResult graphql.Labels 561 ExpectedErr error 562 }{ 563 { 564 Name: "Success", 565 TransactionerFn: txGen.ThatSucceeds, 566 ServiceFn: func() *automock.RuntimeContextService { 567 svc := &automock.RuntimeContextService{} 568 svc.On("ListLabels", contextParam, id).Return(modelLabels, nil).Once() 569 return svc 570 }, 571 InputKey: nil, 572 ExpectedResult: gqlLabels, 573 ExpectedErr: nil, 574 }, 575 { 576 Name: "Success when labels are filtered", 577 TransactionerFn: txGen.ThatSucceeds, 578 ServiceFn: func() *automock.RuntimeContextService { 579 svc := &automock.RuntimeContextService{} 580 svc.On("ListLabels", contextParam, id).Return(modelLabels, nil).Once() 581 return svc 582 }, 583 InputKey: &labelKey1, 584 ExpectedResult: gqlLabels1, 585 ExpectedErr: nil, 586 }, 587 { 588 Name: "Success returns nil when labels not found", 589 TransactionerFn: txGen.ThatSucceeds, 590 ServiceFn: func() *automock.RuntimeContextService { 591 svc := &automock.RuntimeContextService{} 592 svc.On("ListLabels", contextParam, id).Return(nil, errors.New("doesn't exist")).Once() 593 return svc 594 }, 595 InputKey: &labelKey1, 596 ExpectedResult: nil, 597 ExpectedErr: nil, 598 }, 599 { 600 Name: "Returns error when transaction begin failed", 601 TransactionerFn: txGen.ThatFailsOnBegin, 602 ServiceFn: func() *automock.RuntimeContextService { 603 svc := &automock.RuntimeContextService{} 604 return svc 605 }, 606 InputKey: &labelKey1, 607 ExpectedResult: nil, 608 ExpectedErr: testErr, 609 }, 610 { 611 Name: "Returns error when label listing failed", 612 TransactionerFn: txGen.ThatDoesntExpectCommit, 613 ServiceFn: func() *automock.RuntimeContextService { 614 svc := &automock.RuntimeContextService{} 615 svc.On("ListLabels", contextParam, id).Return(nil, testErr).Once() 616 return svc 617 }, 618 InputKey: &labelKey1, 619 ExpectedResult: nil, 620 ExpectedErr: testErr, 621 }, 622 { 623 Name: "Returns error when transaction commit failed", 624 TransactionerFn: txGen.ThatFailsOnCommit, 625 ServiceFn: func() *automock.RuntimeContextService { 626 svc := &automock.RuntimeContextService{} 627 svc.On("ListLabels", contextParam, id).Return(modelLabels, nil).Once() 628 return svc 629 }, 630 InputKey: nil, 631 ExpectedResult: nil, 632 ExpectedErr: testErr, 633 }, 634 } 635 636 for _, testCase := range testCases { 637 t.Run(testCase.Name, func(t *testing.T) { 638 persistTx, transact := testCase.TransactionerFn() 639 svc := testCase.ServiceFn() 640 641 resolver := runtimectx.NewResolver(transact, svc, nil) 642 643 // WHEN 644 result, err := resolver.Labels(context.TODO(), gqlRuntimeContext, testCase.InputKey) 645 646 // then 647 assert.Equal(t, testCase.ExpectedResult, result) 648 assert.Equal(t, testCase.ExpectedErr, err) 649 650 mock.AssertExpectationsForObjects(t, svc, transact, persistTx) 651 }) 652 } 653 }