flamingo.me/flamingo-commerce/v3@v3.11.0/cart/application/cartReceiver_test.go (about) 1 package application_test 2 3 import ( 4 "context" 5 "fmt" 6 "reflect" 7 "testing" 8 9 "flamingo.me/flamingo/v3/core/auth" 10 authMock "flamingo.me/flamingo/v3/core/auth/mock" 11 "flamingo.me/flamingo/v3/framework/flamingo" 12 "flamingo.me/flamingo/v3/framework/web" 13 "github.com/pkg/errors" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/mock" 16 "github.com/stretchr/testify/require" 17 18 cartApplication "flamingo.me/flamingo-commerce/v3/cart/application" 19 cartDomain "flamingo.me/flamingo-commerce/v3/cart/domain/cart" 20 "flamingo.me/flamingo-commerce/v3/cart/domain/decorator" 21 "flamingo.me/flamingo-commerce/v3/cart/domain/events" 22 "flamingo.me/flamingo-commerce/v3/cart/domain/placeorder" 23 cartInfrastructure "flamingo.me/flamingo-commerce/v3/cart/infrastructure" 24 productDomain "flamingo.me/flamingo-commerce/v3/product/domain" 25 ) 26 27 type ( 28 // MockGuestCartServiceAdapter 29 MockGuestCartServiceAdapter struct { 30 Behaviour cartDomain.ModifyBehaviour 31 } 32 ) 33 34 var ( 35 // test interface implementation 36 _ cartDomain.GuestCartService = (*MockGuestCartServiceAdapter)(nil) 37 ) 38 39 func (m *MockGuestCartServiceAdapter) GetCart(ctx context.Context, cartID string) (*cartDomain.Cart, error) { 40 return &cartDomain.Cart{ 41 ID: "mock_guest_cart", 42 }, nil 43 } 44 45 func (m *MockGuestCartServiceAdapter) GetNewCart(ctx context.Context) (*cartDomain.Cart, error) { 46 return &cartDomain.Cart{ 47 ID: "mock_guest_cart", 48 }, nil 49 } 50 51 func (m *MockGuestCartServiceAdapter) GetModifyBehaviour(context.Context) (cartDomain.ModifyBehaviour, error) { 52 return m.Behaviour, nil 53 } 54 55 func (m *MockGuestCartServiceAdapter) RestoreCart(ctx context.Context, cart cartDomain.Cart) (*cartDomain.Cart, error) { 56 restoredCart := cart 57 restoredCart.ID = "1111" 58 return &restoredCart, nil 59 } 60 61 var ( 62 // test interface implementation 63 _ cartDomain.GuestCartService = (*MockGuestCartServiceAdapterError)(nil) 64 ) 65 66 type ( 67 // MockGuestCartServiceAdapter with error on GetCart 68 MockGuestCartServiceAdapterError struct{} 69 ) 70 71 func (m *MockGuestCartServiceAdapterError) GetCart(ctx context.Context, cartID string) (*cartDomain.Cart, error) { 72 return nil, errors.New("defective") 73 } 74 75 func (m *MockGuestCartServiceAdapterError) GetNewCart(ctx context.Context) (*cartDomain.Cart, error) { 76 return nil, errors.New("defective") 77 } 78 79 func (m *MockGuestCartServiceAdapterError) GetModifyBehaviour(context.Context) (cartDomain.ModifyBehaviour, error) { 80 // get guest behaviour 81 return new(cartInfrastructure.DefaultCartBehaviour), nil 82 } 83 84 func (m *MockGuestCartServiceAdapterError) RestoreCart(ctx context.Context, cart cartDomain.Cart) (*cartDomain.Cart, error) { 85 return nil, errors.New("defective") 86 } 87 88 // MockCustomerCartService 89 90 type ( 91 MockCustomerCartService struct { 92 Behaviour cartDomain.ModifyBehaviour 93 } 94 ) 95 96 var ( 97 // test interface implementation 98 _ cartDomain.CustomerCartService = (*MockCustomerCartService)(nil) 99 ) 100 101 func (m *MockCustomerCartService) GetModifyBehaviour(context.Context, auth.Identity) (cartDomain.ModifyBehaviour, error) { 102 // customer behaviour 103 return m.Behaviour, nil 104 } 105 106 func (m *MockCustomerCartService) GetCart(ctx context.Context, identity auth.Identity, cartID string) (*cartDomain.Cart, error) { 107 return &cartDomain.Cart{ 108 ID: "mock_customer_cart", 109 }, nil 110 } 111 112 func (m *MockCustomerCartService) RestoreCart(ctx context.Context, identity auth.Identity, cart cartDomain.Cart) (*cartDomain.Cart, error) { 113 panic("implement me") 114 } 115 116 // MockProductService 117 118 type ( 119 MockProductService struct{} 120 ) 121 122 func (m *MockProductService) Get(ctx context.Context, marketplaceCode string) (productDomain.BasicProduct, error) { 123 mockProduct := new(productDomain.SimpleProduct) 124 125 mockProduct.Identifier = "mock_product" 126 127 return mockProduct, nil 128 } 129 130 // MockCartCache 131 132 type ( 133 MockCartCache struct { 134 CachedCart *cartDomain.Cart 135 } 136 ) 137 138 func (m *MockCartCache) GetCart(context.Context, *web.Session, cartApplication.CartCacheIdentifier) (*cartDomain.Cart, error) { 139 return m.CachedCart, nil 140 } 141 142 func (m *MockCartCache) CacheCart(ctx context.Context, s *web.Session, cci cartApplication.CartCacheIdentifier, cart *cartDomain.Cart) error { 143 m.CachedCart = cart 144 return nil 145 } 146 147 func (m *MockCartCache) Invalidate(context.Context, *web.Session, cartApplication.CartCacheIdentifier) error { 148 return nil 149 } 150 151 func (m *MockCartCache) Delete(context.Context, *web.Session, cartApplication.CartCacheIdentifier) error { 152 return nil 153 } 154 155 func (m *MockCartCache) DeleteAll(context.Context, *web.Session) error { 156 return nil 157 } 158 159 func (m *MockCartCache) BuildIdentifier(context.Context, *web.Session) (cartApplication.CartCacheIdentifier, error) { 160 return cartApplication.CartCacheIdentifier{}, nil 161 } 162 163 // MockEventPublisher 164 165 type ( 166 MockEventPublisher struct { 167 mock.Mock 168 } 169 ) 170 171 var ( 172 _ events.EventPublisher = (*MockEventPublisher)(nil) 173 ) 174 175 func (m *MockEventPublisher) PublishAddToCartEvent(ctx context.Context, cart *cartDomain.Cart, marketPlaceCode string, variantMarketPlaceCode string, qty int) { 176 m.Called() 177 } 178 179 func (m *MockEventPublisher) PublishChangedQtyInCartEvent(ctx context.Context, cart *cartDomain.Cart, item *cartDomain.Item, qtyBefore int, qtyAfter int) { 180 m.Called() 181 } 182 183 func (m *MockEventPublisher) PublishOrderPlacedEvent(ctx context.Context, cart *cartDomain.Cart, placedOrderInfos placeorder.PlacedOrderInfos) { 184 m.Called() 185 } 186 187 type ( 188 MockDeliveryInfoBuilder struct{} 189 ) 190 191 func (m *MockDeliveryInfoBuilder) BuildByDeliveryCode(deliveryCode string) (*cartDomain.DeliveryInfo, error) { 192 return &cartDomain.DeliveryInfo{}, nil 193 } 194 195 type ( 196 MockEventRouter struct { 197 mock.Mock 198 } 199 ) 200 201 var _ flamingo.EventRouter = new(MockEventRouter) 202 203 func (m *MockEventRouter) Dispatch(ctx context.Context, event flamingo.Event) { 204 // we just write the event type and the marketplace code to the mock, so we don't have to compare 205 // the complete cart 206 switch eventType := event.(type) { 207 case *events.AddToCartEvent: 208 m.Called(ctx, fmt.Sprintf("%T", event), eventType.MarketplaceCode) 209 } 210 } 211 212 func TestCartReceiverService_ShouldHaveGuestCart(t *testing.T) { 213 type fields struct { 214 GuestCartService cartDomain.GuestCartService 215 CustomerCartService cartDomain.CustomerCartService 216 CartDecoratorFactory *decorator.DecoratedCartFactory 217 Logger flamingo.Logger 218 CartCache cartApplication.CartCache 219 } 220 type args struct { 221 session *web.Session 222 } 223 tests := []struct { 224 name string 225 fields fields 226 args args 227 want bool 228 }{ 229 { 230 name: "has session key", 231 fields: fields{ 232 GuestCartService: new(MockGuestCartServiceAdapter), 233 CustomerCartService: new(MockCustomerCartService), 234 CartDecoratorFactory: func() *decorator.DecoratedCartFactory { 235 result := &decorator.DecoratedCartFactory{} 236 result.Inject( 237 &MockProductService{}, 238 flamingo.NullLogger{}, 239 ) 240 241 return result 242 }(), 243 Logger: flamingo.NullLogger{}, 244 CartCache: new(MockCartCache), 245 }, 246 args: args{ 247 session: web.EmptySession().Store(cartApplication.GuestCartSessionKey, struct{}{}), 248 }, 249 want: true, 250 }, { 251 name: "doesn't have session key", 252 fields: fields{ 253 GuestCartService: new(MockGuestCartServiceAdapter), 254 CustomerCartService: new(MockCustomerCartService), 255 CartDecoratorFactory: func() *decorator.DecoratedCartFactory { 256 result := &decorator.DecoratedCartFactory{} 257 result.Inject( 258 &MockProductService{}, 259 flamingo.NullLogger{}, 260 ) 261 262 return result 263 }(), 264 Logger: flamingo.NullLogger{}, 265 CartCache: new(MockCartCache), 266 }, 267 args: args{ 268 session: web.EmptySession().Store("arbitrary_and_wrong_key", struct{}{}), 269 }, 270 271 want: false, 272 }, 273 } 274 275 for _, tt := range tests { 276 t.Run(tt.name, func(t *testing.T) { 277 cs := &cartApplication.CartReceiverService{} 278 cs.Inject( 279 tt.fields.GuestCartService, 280 tt.fields.CustomerCartService, 281 tt.fields.CartDecoratorFactory, 282 nil, 283 tt.fields.Logger, 284 nil, 285 &struct { 286 CartCache cartApplication.CartCache `inject:",optional"` 287 }{ 288 CartCache: tt.fields.CartCache, 289 }, 290 ) 291 292 got := cs.ShouldHaveGuestCart(tt.args.session) 293 294 if got != tt.want { 295 t.Errorf("CartReceiverService.ShouldHaveGuestCart() = %v, wantType0 %v", got, tt.want) 296 } 297 }) 298 } 299 } 300 301 func TestCartReceiverService_ViewGuestCart(t *testing.T) { 302 type fields struct { 303 GuestCartService cartDomain.GuestCartService 304 CustomerCartService cartDomain.CustomerCartService 305 CartDecoratorFactory *decorator.DecoratedCartFactory 306 Logger flamingo.Logger 307 CartCache cartApplication.CartCache 308 } 309 type args struct { 310 ctx context.Context 311 session *web.Session 312 } 313 tests := []struct { 314 name string 315 fields fields 316 args args 317 want *cartDomain.Cart 318 wantErr bool 319 wantMessageErr string 320 }{ 321 { 322 name: "has no guest cart", 323 fields: fields{ 324 GuestCartService: new(MockGuestCartServiceAdapter), 325 CustomerCartService: new(MockCustomerCartService), 326 CartDecoratorFactory: func() *decorator.DecoratedCartFactory { 327 result := &decorator.DecoratedCartFactory{} 328 result.Inject( 329 &MockProductService{}, 330 flamingo.NullLogger{}, 331 ) 332 333 return result 334 }(), 335 Logger: flamingo.NullLogger{}, 336 CartCache: new(MockCartCache), 337 }, 338 args: args{ 339 ctx: context.Background(), 340 session: web.EmptySession().Store("stuff", "some_malformed_id"), 341 }, 342 want: &cartDomain.Cart{}, 343 wantErr: false, 344 wantMessageErr: "", 345 }, { 346 name: "failed guest cart get", 347 fields: fields{ 348 GuestCartService: new(MockGuestCartServiceAdapterError), 349 CustomerCartService: new(MockCustomerCartService), 350 CartDecoratorFactory: func() *decorator.DecoratedCartFactory { 351 result := &decorator.DecoratedCartFactory{} 352 result.Inject( 353 &MockProductService{}, 354 flamingo.NullLogger{}, 355 ) 356 357 return result 358 }(), 359 Logger: flamingo.NullLogger{}, 360 CartCache: new(MockCartCache), 361 }, 362 args: args{ 363 ctx: context.Background(), 364 session: web.EmptySession().Store(cartApplication.GuestCartSessionKey, "some_guest_id"), 365 }, 366 want: nil, 367 wantErr: true, 368 wantMessageErr: cartApplication.ErrTemporaryCartService.Error(), 369 }, { 370 name: "guest cart get without error", 371 fields: fields{ 372 GuestCartService: new(MockGuestCartServiceAdapter), 373 CustomerCartService: new(MockCustomerCartService), 374 CartDecoratorFactory: func() *decorator.DecoratedCartFactory { 375 result := &decorator.DecoratedCartFactory{} 376 result.Inject( 377 &MockProductService{}, 378 flamingo.NullLogger{}, 379 ) 380 381 return result 382 }(), 383 Logger: flamingo.NullLogger{}, 384 CartCache: new(MockCartCache), 385 }, 386 args: args{ 387 ctx: context.Background(), 388 session: web.EmptySession().Store(cartApplication.GuestCartSessionKey, "some_guest_id"), 389 }, 390 want: &cartDomain.Cart{ 391 ID: "mock_guest_cart", 392 }, 393 wantErr: false, 394 wantMessageErr: "", 395 }, 396 } 397 398 for _, tt := range tests { 399 t.Run(tt.name, func(t *testing.T) { 400 cs := &cartApplication.CartReceiverService{} 401 cs.Inject( 402 tt.fields.GuestCartService, 403 tt.fields.CustomerCartService, 404 tt.fields.CartDecoratorFactory, 405 nil, 406 tt.fields.Logger, 407 nil, 408 &struct { 409 CartCache cartApplication.CartCache `inject:",optional"` 410 }{ 411 CartCache: tt.fields.CartCache, 412 }, 413 ) 414 415 got, err := cs.ViewGuestCart(tt.args.ctx, tt.args.session) 416 if (err != nil) != tt.wantErr { 417 t.Errorf("CartReceiverService.ViewGuestCart() error = %v, wantErr %v", err, tt.wantErr) 418 419 return 420 } 421 422 if err != nil && err.Error() != tt.wantMessageErr { 423 t.Errorf("Error doesn't match - error = %v, wantMessageErr %v", err, tt.wantMessageErr) 424 425 return 426 } 427 428 if !reflect.DeepEqual(got, tt.want) { 429 t.Errorf("CartReceiverService.ViewGuestCart() = %v, wantType0 %v", got, tt.want) 430 } 431 }) 432 } 433 } 434 435 func TestCartReceiverService_DecorateCart(t *testing.T) { 436 type fields struct { 437 GuestCartService cartDomain.GuestCartService 438 CustomerCartService cartDomain.CustomerCartService 439 CartDecoratorFactory *decorator.DecoratedCartFactory 440 Logger flamingo.Logger 441 CartCache cartApplication.CartCache 442 } 443 type args struct { 444 ctx context.Context 445 cart *cartDomain.Cart 446 } 447 tests := []struct { 448 name string 449 fields fields 450 args args 451 want *decorator.DecoratedCart 452 wantErr bool 453 wantMessageErr string 454 wantDecoratedItemsLength int 455 }{ 456 { 457 name: "error b/c no cart supplied", 458 fields: fields{ 459 GuestCartService: new(MockGuestCartServiceAdapter), 460 CustomerCartService: new(MockCustomerCartService), 461 CartDecoratorFactory: func() *decorator.DecoratedCartFactory { 462 result := &decorator.DecoratedCartFactory{} 463 result.Inject( 464 &MockProductService{}, 465 flamingo.NullLogger{}, 466 ) 467 468 return result 469 }(), 470 Logger: flamingo.NullLogger{}, 471 CartCache: new(MockCartCache), 472 }, 473 args: args{ 474 ctx: context.Background(), 475 cart: nil, 476 }, 477 wantErr: true, 478 wantMessageErr: "no cart given", 479 wantDecoratedItemsLength: 0, 480 }, { 481 name: "basic decoration of cart", 482 fields: fields{ 483 GuestCartService: new(MockGuestCartServiceAdapter), 484 CustomerCartService: new(MockCustomerCartService), 485 CartDecoratorFactory: func() *decorator.DecoratedCartFactory { 486 result := &decorator.DecoratedCartFactory{} 487 result.Inject( 488 &MockProductService{}, 489 flamingo.NullLogger{}, 490 ) 491 492 return result 493 }(), 494 Logger: flamingo.NullLogger{}, 495 CartCache: new(MockCartCache), 496 }, 497 args: args{ 498 ctx: context.Background(), 499 cart: &cartDomain.Cart{ 500 ID: "some_test_cart", 501 Deliveries: []cartDomain.Delivery{ 502 { 503 Cartitems: []cartDomain.Item{ 504 { 505 ID: "test_id", 506 }, 507 }, 508 }, 509 }, 510 }, 511 }, 512 wantErr: false, 513 wantMessageErr: "", 514 wantDecoratedItemsLength: 1, 515 }, 516 } 517 518 for _, tt := range tests { 519 t.Run(tt.name, func(t *testing.T) { 520 cs := &cartApplication.CartReceiverService{} 521 cs.Inject( 522 tt.fields.GuestCartService, 523 tt.fields.CustomerCartService, 524 tt.fields.CartDecoratorFactory, 525 nil, 526 tt.fields.Logger, 527 nil, 528 &struct { 529 CartCache cartApplication.CartCache `inject:",optional"` 530 }{ 531 CartCache: tt.fields.CartCache, 532 }, 533 ) 534 535 got, err := cs.DecorateCart(tt.args.ctx, tt.args.cart) 536 537 if (err != nil) != tt.wantErr { 538 t.Errorf("CartReceiverService.DecorateCart() error = %v, wantErr %v", err, tt.wantErr) 539 540 return 541 } 542 543 if err != nil && err.Error() != tt.wantMessageErr { 544 t.Errorf("Error doesn't match - error = %v, wantMessageErr %v", err, tt.wantMessageErr) 545 546 return 547 } 548 549 if tt.wantDecoratedItemsLength > 0 { 550 for _, decoratedDeliveryItem := range got.DecoratedDeliveries { 551 if len(decoratedDeliveryItem.DecoratedItems) != tt.wantDecoratedItemsLength { 552 t.Errorf("Mismatch of expected Decorated Items, got %d, expected %d", len(decoratedDeliveryItem.DecoratedItems), tt.wantDecoratedItemsLength) 553 } 554 } 555 } 556 }) 557 } 558 } 559 560 func TestCartReceiverService_GetDecoratedCart(t *testing.T) { 561 type fields struct { 562 GuestCartService cartDomain.GuestCartService 563 CustomerCartService cartDomain.CustomerCartService 564 CartDecoratorFactory *decorator.DecoratedCartFactory 565 Logger flamingo.Logger 566 CartCache cartApplication.CartCache 567 } 568 type args struct { 569 ctx context.Context 570 session *web.Session 571 } 572 tests := []struct { 573 name string 574 fields fields 575 args args 576 want *decorator.DecoratedCart 577 wantBehaviour cartDomain.ModifyBehaviour 578 wantErr bool 579 }{ 580 { 581 name: "decorated cart not found", 582 fields: fields{ 583 GuestCartService: new(MockGuestCartServiceAdapterError), 584 CustomerCartService: new(MockCustomerCartService), 585 CartDecoratorFactory: func() *decorator.DecoratedCartFactory { 586 result := &decorator.DecoratedCartFactory{} 587 result.Inject( 588 &MockProductService{}, 589 flamingo.NullLogger{}, 590 ) 591 592 return result 593 }(), 594 Logger: flamingo.NullLogger{}, 595 CartCache: new(MockCartCache), 596 }, 597 args: args{ 598 ctx: context.Background(), 599 session: web.EmptySession().Store("some_nonvalid_key", "some_guest_id"), 600 }, 601 want: nil, 602 wantBehaviour: nil, 603 wantErr: true, 604 }, { 605 name: "decorated cart found", 606 fields: fields{ 607 GuestCartService: &MockGuestCartServiceAdapter{Behaviour: &cartInfrastructure.DefaultCartBehaviour{}}, 608 CustomerCartService: new(MockCustomerCartService), 609 CartDecoratorFactory: func() *decorator.DecoratedCartFactory { 610 result := &decorator.DecoratedCartFactory{} 611 result.Inject( 612 &MockProductService{}, 613 flamingo.NullLogger{}, 614 ) 615 616 return result 617 }(), 618 Logger: flamingo.NullLogger{}, 619 CartCache: new(MockCartCache), 620 }, 621 args: args{ 622 ctx: context.Background(), 623 session: web.EmptySession().Store("some_nonvalid_key", "some_guest_id"), 624 }, 625 want: &decorator.DecoratedCart{}, 626 wantBehaviour: &cartInfrastructure.DefaultCartBehaviour{}, 627 wantErr: false, 628 }, 629 } 630 631 for _, tt := range tests { 632 t.Run(tt.name, func(t *testing.T) { 633 cs := &cartApplication.CartReceiverService{} 634 cs.Inject( 635 tt.fields.GuestCartService, 636 tt.fields.CustomerCartService, 637 tt.fields.CartDecoratorFactory, 638 nil, 639 tt.fields.Logger, 640 nil, 641 &struct { 642 CartCache cartApplication.CartCache `inject:",optional"` 643 }{ 644 CartCache: tt.fields.CartCache, 645 }, 646 ) 647 648 got, gotBehaviour, err := cs.GetDecoratedCart(tt.args.ctx, tt.args.session) 649 650 if (err != nil) != tt.wantErr { 651 t.Errorf("CartReceiverService.GetDecoratedCart() error = %v, wantErr %v", err, tt.wantErr) 652 653 return 654 } 655 656 if tt.want == nil { 657 if !reflect.DeepEqual(got, tt.want) { 658 t.Errorf("CartReceiverService.GetDecoratedCart() got = %v, want %v", got, tt.want) 659 660 return 661 } 662 } else { 663 gotType := reflect.TypeOf(got).Elem() 664 wantType := reflect.TypeOf(tt.want).Elem() 665 if wantType != gotType { 666 t.Error("Return Type for want doesn't match") 667 668 return 669 } 670 } 671 672 if tt.wantBehaviour == nil { 673 if !reflect.DeepEqual(gotBehaviour, tt.wantBehaviour) { 674 t.Errorf("CartReceiverService.GetDecoratedCart() gotBehaviour = %v, wantBehaviour %v", gotBehaviour, tt.wantBehaviour) 675 676 return 677 } 678 } else { 679 gotType1 := reflect.TypeOf(gotBehaviour).Elem() 680 wantType1 := reflect.TypeOf(tt.wantBehaviour).Elem() 681 if wantType1 != gotType1 { 682 t.Errorf("Return Type for want doesn't match, got = %v, want = %v", gotType1, wantType1) 683 684 return 685 } 686 } 687 688 if !reflect.DeepEqual(gotBehaviour, tt.wantBehaviour) { 689 t.Errorf("CartReceiverService.GetDecoratedCart() gotBehaviour = %v, wantBehaviour %v", gotBehaviour, tt.wantBehaviour) 690 691 return 692 } 693 }) 694 } 695 } 696 697 func TestCartReceiverService_RestoreCart(t *testing.T) { 698 type fields struct { 699 guestCartService cartDomain.GuestCartService 700 customerCartService cartDomain.CustomerCartService 701 cartDecoratorFactory *decorator.DecoratedCartFactory 702 logger flamingo.Logger 703 cartCache cartApplication.CartCache 704 } 705 type args struct { 706 ctx context.Context 707 session *web.Session 708 cartToRestore cartDomain.Cart 709 } 710 tests := []struct { 711 name string 712 fields fields 713 args args 714 want *cartDomain.Cart 715 wantErr bool 716 wantGuestCartSessionID bool 717 wantCartStoredInCache bool 718 }{ 719 { 720 name: "restore guest cart without error", 721 fields: fields{ 722 guestCartService: &MockGuestCartServiceAdapter{}, 723 logger: &flamingo.NullLogger{}, 724 cartCache: &MockCartCache{}, 725 }, 726 args: args{ 727 ctx: web.ContextWithSession(context.Background(), web.EmptySession()), 728 session: web.EmptySession(), 729 cartToRestore: cartDomain.Cart{ 730 ID: "1234", 731 BillingAddress: &cartDomain.Address{ 732 Firstname: "Test", 733 Lastname: "Test", 734 Email: "test@test.xy", 735 }, 736 Deliveries: []cartDomain.Delivery{ 737 { 738 DeliveryInfo: cartDomain.DeliveryInfo{ 739 Code: "pickup", 740 Workflow: "pickup", 741 }, 742 Cartitems: []cartDomain.Item{ 743 { 744 ID: "1", 745 ExternalReference: "sku-1", 746 MarketplaceCode: "sku-1", 747 VariantMarketPlaceCode: "", 748 ProductName: "Product #1", 749 SourceID: "", 750 Qty: 2, 751 }, 752 }, 753 ShippingItem: cartDomain.ShippingItem{}, 754 }, 755 }, 756 }, 757 }, 758 want: &cartDomain.Cart{ 759 ID: "1111", 760 BillingAddress: &cartDomain.Address{ 761 Firstname: "Test", 762 Lastname: "Test", 763 Email: "test@test.xy", 764 }, 765 Deliveries: []cartDomain.Delivery{ 766 { 767 DeliveryInfo: cartDomain.DeliveryInfo{ 768 Code: "pickup", 769 Workflow: "pickup", 770 }, 771 Cartitems: []cartDomain.Item{ 772 { 773 ID: "1", 774 ExternalReference: "sku-1", 775 MarketplaceCode: "sku-1", 776 VariantMarketPlaceCode: "", 777 ProductName: "Product #1", 778 SourceID: "", 779 Qty: 2, 780 }, 781 }, 782 ShippingItem: cartDomain.ShippingItem{}, 783 }, 784 }, 785 }, 786 wantErr: false, 787 wantGuestCartSessionID: true, 788 wantCartStoredInCache: true, 789 }, 790 { 791 name: "restore guest cart with error", 792 fields: fields{ 793 guestCartService: &MockGuestCartServiceAdapterError{}, 794 795 logger: &flamingo.NullLogger{}, 796 cartCache: &MockCartCache{}, 797 }, 798 args: args{ 799 ctx: web.ContextWithSession(context.Background(), web.EmptySession()), 800 session: web.EmptySession(), 801 cartToRestore: cartDomain.Cart{ 802 ID: "1234", 803 BillingAddress: &cartDomain.Address{ 804 Firstname: "Test", 805 Lastname: "Test", 806 Email: "test@test.xy", 807 }, 808 Deliveries: []cartDomain.Delivery{ 809 { 810 DeliveryInfo: cartDomain.DeliveryInfo{ 811 Code: "pickup", 812 Workflow: "pickup", 813 }, 814 Cartitems: []cartDomain.Item{ 815 { 816 ID: "1", 817 ExternalReference: "sku-1", 818 MarketplaceCode: "sku-1", 819 VariantMarketPlaceCode: "", 820 ProductName: "Product #1", 821 SourceID: "", 822 Qty: 2, 823 }, 824 }, 825 ShippingItem: cartDomain.ShippingItem{}, 826 }, 827 }, 828 }, 829 }, 830 want: nil, 831 wantErr: true, 832 wantGuestCartSessionID: false, 833 wantCartStoredInCache: false, 834 }, 835 } 836 for _, tt := range tests { 837 t.Run(tt.name, func(t *testing.T) { 838 cs := &cartApplication.CartReceiverService{} 839 cs.Inject( 840 tt.fields.guestCartService, 841 tt.fields.customerCartService, 842 tt.fields.cartDecoratorFactory, 843 nil, 844 tt.fields.logger, 845 nil, 846 &struct { 847 CartCache cartApplication.CartCache `inject:",optional"` 848 }{ 849 CartCache: tt.fields.cartCache, 850 }, 851 ) 852 got, err := cs.RestoreCart(tt.args.ctx, tt.args.session, tt.args.cartToRestore) 853 if (err != nil) != tt.wantErr { 854 t.Errorf("RestoreCart() error = %v, wantErr %v", err, tt.wantErr) 855 return 856 } 857 if !reflect.DeepEqual(got, tt.want) { 858 t.Errorf("RestoreCart() got = %v, want %v", got, tt.want) 859 } 860 861 sessionGot, found := tt.args.session.Load(cartApplication.GuestCartSessionKey) 862 if found != tt.wantGuestCartSessionID { 863 t.Error("GuestCartID not found in session") 864 } 865 866 if found == true && tt.want != nil { 867 if !reflect.DeepEqual(tt.want.ID, sessionGot) { 868 t.Errorf("GuestCartID in session does not match restored cart got = %v, want %v", got, tt.wantGuestCartSessionID) 869 } 870 } 871 872 if tt.wantCartStoredInCache && tt.fields.cartCache != nil { 873 cart, _ := tt.fields.cartCache.GetCart(context.Background(), nil, cartApplication.CartCacheIdentifier{}) 874 if cart == nil { 875 t.Error("Cart not found in cart cache") 876 } 877 } 878 }) 879 } 880 } 881 882 func TestCartReceiverService_ModifyBehaviour(t *testing.T) { 883 t.Run("get guest behaviour", func(t *testing.T) { 884 mockBehaviour := &cartInfrastructure.DefaultCartBehaviour{} 885 cs := &cartApplication.CartReceiverService{} 886 cs.Inject( 887 &MockGuestCartServiceAdapter{Behaviour: mockBehaviour}, 888 &MockCustomerCartService{}, 889 &decorator.DecoratedCartFactory{}, 890 &auth.WebIdentityService{}, 891 flamingo.NullLogger{}, 892 nil, 893 &struct { 894 CartCache cartApplication.CartCache `inject:",optional"` 895 }{ 896 CartCache: &MockCartCache{}, 897 }, 898 ) 899 900 behaviour, err := cs.ModifyBehaviour(context.Background()) 901 902 assert.NoError(t, err) 903 require.NotNil(t, behaviour) 904 assert.Same(t, behaviour, mockBehaviour) 905 }) 906 907 t.Run("get customer behaviour", func(t *testing.T) { 908 mockIdentifier := new(authMock.Identifier).SetIdentifyMethod( 909 func(identifier *authMock.Identifier, ctx context.Context, request *web.Request) (auth.Identity, error) { 910 return &authMock.Identity{Sub: "foo"}, nil 911 }, 912 ) 913 cs := &cartApplication.CartReceiverService{} 914 mockBehaviour := &cartInfrastructure.DefaultCartBehaviour{} 915 cs.Inject( 916 &MockGuestCartServiceAdapter{}, 917 &MockCustomerCartService{Behaviour: mockBehaviour}, 918 &decorator.DecoratedCartFactory{}, 919 new(auth.WebIdentityService).Inject([]auth.RequestIdentifier{mockIdentifier}, nil, nil, nil), 920 flamingo.NullLogger{}, 921 nil, 922 &struct { 923 CartCache cartApplication.CartCache `inject:",optional"` 924 }{ 925 CartCache: &MockCartCache{}, 926 }, 927 ) 928 929 behaviour, err := cs.ModifyBehaviour(context.Background()) 930 931 assert.NoError(t, err) 932 require.NotNil(t, behaviour) 933 assert.Same(t, behaviour, mockBehaviour) 934 }) 935 }