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  }