flamingo.me/flamingo-commerce/v3@v3.11.0/cart/application/cartCache_test.go (about)

     1  package application_test
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"testing"
     7  	"time"
     8  
     9  	"flamingo.me/flamingo-commerce/v3/price/domain"
    10  
    11  	"flamingo.me/flamingo-commerce/v3/cart/application"
    12  	"flamingo.me/flamingo-commerce/v3/cart/domain/cart"
    13  	"flamingo.me/flamingo/v3/framework/flamingo"
    14  	"flamingo.me/flamingo/v3/framework/web"
    15  )
    16  
    17  var (
    18  	_ application.CartCache = new(application.CartSessionCache)
    19  )
    20  
    21  func TestCartCacheIdentifier_CacheKey(t *testing.T) {
    22  	type fields struct {
    23  		GuestCartID    string
    24  		IsCustomerCart bool
    25  		CustomerID     string
    26  	}
    27  	tests := []struct {
    28  		name   string
    29  		fields fields
    30  		want   string
    31  	}{
    32  		{
    33  			name: "basic test",
    34  			fields: fields{
    35  				GuestCartID:    "guest_cart_id",
    36  				IsCustomerCart: false,
    37  				CustomerID:     "customer_id",
    38  			},
    39  			want: "cart_customer_id_guest_cart_id",
    40  		},
    41  	}
    42  
    43  	for _, tt := range tests {
    44  		t.Run(tt.name, func(t *testing.T) {
    45  			ci := &application.CartCacheIdentifier{
    46  				GuestCartID:    tt.fields.GuestCartID,
    47  				IsCustomerCart: tt.fields.IsCustomerCart,
    48  				CustomerID:     tt.fields.CustomerID,
    49  			}
    50  
    51  			if got := ci.CacheKey(); got != tt.want {
    52  				t.Errorf("CartCacheIdentifier.CacheKey() = %v, wantType0 %v", got, tt.want)
    53  			}
    54  		})
    55  	}
    56  }
    57  
    58  func TestCartSessionCache_GetCart(t *testing.T) {
    59  	type args struct {
    60  		ctx     context.Context
    61  		session *web.Session
    62  		id      application.CartCacheIdentifier
    63  	}
    64  	tests := []struct {
    65  		name           string
    66  		args           args
    67  		want           *cart.Cart
    68  		wantErr        bool
    69  		wantMessageErr string
    70  	}{
    71  		{
    72  			name: "error for no cart in cache",
    73  			args: args{
    74  				ctx:     context.Background(),
    75  				session: web.EmptySession(),
    76  				id: application.CartCacheIdentifier{
    77  					GuestCartID:    "guest_cart_id",
    78  					IsCustomerCart: false,
    79  					CustomerID:     "customer_id",
    80  				},
    81  			},
    82  			want:           nil,
    83  			wantErr:        true,
    84  			wantMessageErr: "cache entry not found",
    85  		},
    86  		{
    87  			name: "cached cart found/invalid cache entry",
    88  			args: args{
    89  				ctx: context.Background(),
    90  				session: web.EmptySession().Store(
    91  					application.CartSessionCacheCacheKeyPrefix+"cart_customer_id_guest_cart_id",
    92  					application.CachedCartEntry{IsInvalid: true},
    93  				),
    94  				id: application.CartCacheIdentifier{
    95  					GuestCartID:    "guest_cart_id",
    96  					IsCustomerCart: false,
    97  					CustomerID:     "customer_id",
    98  				},
    99  			},
   100  			want:           new(cart.Cart),
   101  			wantErr:        true,
   102  			wantMessageErr: "cache is invalid",
   103  		},
   104  		{
   105  			name: "cached cart found/valid cache entry",
   106  			args: args{
   107  				ctx: context.Background(),
   108  				session: web.EmptySession().Store(
   109  					application.CartSessionCacheCacheKeyPrefix+"cart_customer_id_guest_cart_id",
   110  					application.CachedCartEntry{
   111  						IsInvalid: false,
   112  						ExpiresOn: time.Now().Add(5 * time.Minute),
   113  						Entry:     *getFixtureCartForTest(t),
   114  					},
   115  				),
   116  				id: application.CartCacheIdentifier{
   117  					GuestCartID:    "guest_cart_id",
   118  					IsCustomerCart: false,
   119  					CustomerID:     "customer_id",
   120  				},
   121  			},
   122  			want:           getFixtureCartForTest(t),
   123  			wantErr:        false,
   124  			wantMessageErr: "",
   125  		},
   126  		{
   127  			name: "session contains invalid data at cache key",
   128  			args: args{
   129  				ctx: context.Background(),
   130  				session: web.EmptySession().Store(
   131  					application.CartSessionCacheCacheKeyPrefix+"cart_customer_id_guest_cart_id",
   132  					struct {
   133  						invalidProperty bool
   134  					}{
   135  						invalidProperty: true,
   136  					},
   137  				),
   138  				id: application.CartCacheIdentifier{
   139  					GuestCartID:    "guest_cart_id",
   140  					IsCustomerCart: false,
   141  					CustomerID:     "customer_id",
   142  				},
   143  			},
   144  			want:           nil,
   145  			wantErr:        true,
   146  			wantMessageErr: "cart cache contains invalid data at cache key",
   147  		},
   148  		{
   149  			name: "session contains expired cart cache",
   150  			args: args{
   151  				ctx: context.Background(),
   152  				session: web.EmptySession().Store(application.CartSessionCacheCacheKeyPrefix+"cart_customer_id_guest_cart_id",
   153  					application.CachedCartEntry{
   154  						IsInvalid: false,
   155  						ExpiresOn: time.Now().Add(-1 * time.Second),
   156  					},
   157  				),
   158  				id: application.CartCacheIdentifier{
   159  					GuestCartID:    "guest_cart_id",
   160  					IsCustomerCart: false,
   161  					CustomerID:     "customer_id",
   162  				},
   163  			},
   164  			want:           nil,
   165  			wantErr:        true,
   166  			wantMessageErr: "cache is invalid",
   167  		},
   168  	}
   169  
   170  	for _, tt := range tests {
   171  		t.Run(tt.name, func(t *testing.T) {
   172  			c := &application.CartSessionCache{}
   173  			c.Inject(flamingo.NullLogger{}, nil, nil)
   174  
   175  			got, err := c.GetCart(tt.args.ctx, tt.args.session, tt.args.id)
   176  			if (err != nil) != tt.wantErr {
   177  				t.Errorf("CartSessionCache.GetCart() error = %v, wantErr %v", err, tt.wantErr)
   178  
   179  				return
   180  			}
   181  
   182  			if err != nil && err.Error() != tt.wantMessageErr {
   183  				t.Errorf("Error doesn't match - error = %v, wantMessageErr %v", err, tt.wantMessageErr)
   184  
   185  				return
   186  			}
   187  
   188  			if !reflect.DeepEqual(got, tt.want) {
   189  				t.Errorf("CartSessionCache.GetCart() = %v, wantType0 %v", got, tt.want)
   190  			}
   191  		})
   192  	}
   193  }
   194  
   195  func TestCartSessionCache_CacheCart(t *testing.T) {
   196  	type fields struct {
   197  		config *struct {
   198  			LifetimeSeconds float64 `inject:"config:commerce.cart.cacheLifetime"` // in seconds
   199  		}
   200  	}
   201  	type args struct {
   202  		ctx          context.Context
   203  		session      *web.Session
   204  		id           application.CartCacheIdentifier
   205  		cartForCache *cart.Cart
   206  	}
   207  	tests := []struct {
   208  		name           string
   209  		fields         fields
   210  		args           args
   211  		wantErr        bool
   212  		wantMessageErr string
   213  	}{
   214  		{
   215  			name: "no cart given",
   216  			fields: fields{
   217  				config: &struct {
   218  					LifetimeSeconds float64 `inject:"config:commerce.cart.cacheLifetime"` // in seconds
   219  				}{
   220  					LifetimeSeconds: 300,
   221  				},
   222  			},
   223  			args: args{
   224  				ctx:     context.Background(),
   225  				session: nil,
   226  				id: application.CartCacheIdentifier{
   227  					GuestCartID:    "guest_cart_id",
   228  					IsCustomerCart: false,
   229  					CustomerID:     "",
   230  				},
   231  				cartForCache: nil,
   232  			},
   233  			wantErr:        true,
   234  			wantMessageErr: "no cart given to cache",
   235  		},
   236  		{
   237  			name:   "cart is cached",
   238  			fields: fields{},
   239  			args: args{
   240  				ctx:     context.Background(),
   241  				session: web.EmptySession(),
   242  				id: application.CartCacheIdentifier{
   243  					GuestCartID:    "guest_cart_id",
   244  					IsCustomerCart: false,
   245  					CustomerID:     "",
   246  				},
   247  				cartForCache: new(cart.Cart),
   248  			},
   249  			wantErr:        false,
   250  			wantMessageErr: "",
   251  		},
   252  	}
   253  
   254  	for _, tt := range tests {
   255  		t.Run(tt.name, func(t *testing.T) {
   256  			c := &application.CartSessionCache{}
   257  			c.Inject(flamingo.NullLogger{}, nil, nil)
   258  
   259  			err := c.CacheCart(tt.args.ctx, tt.args.session, tt.args.id, tt.args.cartForCache)
   260  			if (err != nil) != tt.wantErr {
   261  				t.Errorf("CartSessionCache.CacheCart() error = %v, wantErr %v", err, tt.wantErr)
   262  
   263  				return
   264  			}
   265  
   266  			if err != nil && err.Error() != tt.wantMessageErr {
   267  				t.Errorf("Error doesn't match - error = %v, wantMessageErr %v", err, tt.wantMessageErr)
   268  			}
   269  		})
   270  	}
   271  }
   272  
   273  func TestCartSessionCache_CartExpiry(t *testing.T) {
   274  	c := &application.CartSessionCache{}
   275  	c.Inject(
   276  		flamingo.NullLogger{},
   277  		nil,
   278  		&struct {
   279  			LifetimeSeconds float64 `inject:"config:commerce.cart.cacheLifetime"` // in seconds
   280  		}{
   281  			LifetimeSeconds: 1,
   282  		},
   283  	)
   284  
   285  	ctx := context.Background()
   286  	session := web.EmptySession()
   287  
   288  	id := application.CartCacheIdentifier{
   289  		GuestCartID:    "guest_cart_id",
   290  		IsCustomerCart: false,
   291  		CustomerID:     "",
   292  	}
   293  
   294  	cartForCache := new(cart.Cart)
   295  
   296  	err := c.CacheCart(ctx, session, id, cartForCache)
   297  	if err != nil {
   298  		t.Errorf("Failed to cache the cart. Error: %v", err)
   299  	}
   300  
   301  	time.Sleep(1 * time.Second)
   302  
   303  	_, err = c.GetCart(context.Background(), session, id)
   304  	if err != application.ErrCacheIsInvalid {
   305  		t.Error("Expected cache invalid error. Received nil")
   306  		return
   307  	}
   308  }
   309  
   310  func TestCartSessionCache_Invalidate(t *testing.T) {
   311  	type fields struct {
   312  	}
   313  	type args struct {
   314  		ctx     context.Context
   315  		session *web.Session
   316  		id      application.CartCacheIdentifier
   317  	}
   318  	tests := []struct {
   319  		name                  string
   320  		fields                fields
   321  		args                  args
   322  		wantErr               bool
   323  		wantMessageErr        string
   324  		wantCacheEntryInvalid bool
   325  	}{
   326  		{
   327  			name:   "no cache entry",
   328  			fields: fields{},
   329  			args: args{
   330  				ctx:     context.Background(),
   331  				session: web.EmptySession(),
   332  				id: application.CartCacheIdentifier{
   333  					GuestCartID:    "guest_cart_id",
   334  					IsCustomerCart: false,
   335  					CustomerID:     "",
   336  				},
   337  			},
   338  			wantErr:               true,
   339  			wantMessageErr:        "cache entry not found",
   340  			wantCacheEntryInvalid: false,
   341  		},
   342  		{
   343  			name:   "invalidate cache entry",
   344  			fields: fields{},
   345  			args: args{
   346  				ctx: context.Background(),
   347  				session: web.EmptySession().Store(
   348  					application.CartSessionCacheCacheKeyPrefix+"cart__guest_cart_id",
   349  					application.CachedCartEntry{IsInvalid: false},
   350  				),
   351  				id: application.CartCacheIdentifier{
   352  					GuestCartID:    "guest_cart_id",
   353  					IsCustomerCart: false,
   354  					CustomerID:     "",
   355  				},
   356  			},
   357  			wantErr:               false,
   358  			wantMessageErr:        "",
   359  			wantCacheEntryInvalid: true,
   360  		},
   361  	}
   362  
   363  	for _, tt := range tests {
   364  		t.Run(tt.name, func(t *testing.T) {
   365  			c := &application.CartSessionCache{}
   366  			c.Inject(flamingo.NullLogger{}, nil, nil)
   367  
   368  			err := c.Invalidate(tt.args.ctx, tt.args.session, tt.args.id)
   369  
   370  			if (err != nil) != tt.wantErr {
   371  				t.Errorf("CartSessionCache.Invalidate() error = %v, wantErr %v", err, tt.wantErr)
   372  
   373  				return
   374  			}
   375  
   376  			if err != nil && err.Error() != tt.wantMessageErr {
   377  				t.Errorf("Error doesn't match - error = %v, wantMessageErr %v", err, tt.wantMessageErr)
   378  			}
   379  
   380  			if tt.wantCacheEntryInvalid == true {
   381  				for key := range tt.args.session.Keys() {
   382  					if cacheEntry, ok := tt.args.session.Load(key); ok {
   383  						if entry, ok := cacheEntry.(application.CachedCartEntry); ok {
   384  							if entry.IsInvalid != tt.wantCacheEntryInvalid {
   385  								t.Errorf("Cache validity doesnt match - got %v, wantCacheEntryInvalid %v", entry.IsInvalid, tt.wantCacheEntryInvalid)
   386  							}
   387  						}
   388  					}
   389  				}
   390  			}
   391  		})
   392  	}
   393  }
   394  
   395  func TestCartSessionCache_Delete(t *testing.T) {
   396  	type fields struct {
   397  	}
   398  	type args struct {
   399  		ctx     context.Context
   400  		session *web.Session
   401  		id      application.CartCacheIdentifier
   402  	}
   403  	tests := []struct {
   404  		name           string
   405  		fields         fields
   406  		args           args
   407  		wantErr        bool
   408  		wantMessageErr string
   409  	}{
   410  		{
   411  			name:   "cache entry not found for delete",
   412  			fields: fields{},
   413  			args: args{
   414  				ctx:     context.Background(),
   415  				session: web.EmptySession(),
   416  				id: application.CartCacheIdentifier{
   417  					GuestCartID:    "guest_cart_id",
   418  					IsCustomerCart: false,
   419  					CustomerID:     "",
   420  				},
   421  			},
   422  			wantErr:        true,
   423  			wantMessageErr: "cache entry not found",
   424  		},
   425  		{
   426  			name:   "deleted correctly",
   427  			fields: fields{},
   428  			args: args{
   429  				ctx: context.Background(),
   430  				session: web.EmptySession().Store(
   431  					application.CartSessionCacheCacheKeyPrefix+"cart__guest_cart_id",
   432  					application.CachedCartEntry{IsInvalid: false},
   433  				),
   434  				id: application.CartCacheIdentifier{
   435  					GuestCartID:    "guest_cart_id",
   436  					IsCustomerCart: false,
   437  					CustomerID:     "",
   438  				},
   439  			},
   440  			wantErr:        false,
   441  			wantMessageErr: "",
   442  		},
   443  	}
   444  
   445  	for _, tt := range tests {
   446  		t.Run(tt.name, func(t *testing.T) {
   447  			c := &application.CartSessionCache{}
   448  			c.Inject(flamingo.NullLogger{}, nil, nil)
   449  
   450  			err := c.Delete(tt.args.ctx, tt.args.session, tt.args.id)
   451  
   452  			if (err != nil) != tt.wantErr {
   453  				t.Errorf("CartSessionCache.Delete() error = %v, wantErr %v", err, tt.wantErr)
   454  
   455  				return
   456  			}
   457  
   458  			if err != nil && err.Error() != tt.wantMessageErr {
   459  				t.Errorf("Error doesn't match - error = %v, wantMessageErr %v", err, tt.wantMessageErr)
   460  			}
   461  		})
   462  	}
   463  }
   464  
   465  func TestCartSessionCache_DeleteAll(t *testing.T) {
   466  	type fields struct {
   467  	}
   468  	type args struct {
   469  		ctx     context.Context
   470  		session *web.Session
   471  	}
   472  	tests := []struct {
   473  		name                   string
   474  		fields                 fields
   475  		args                   args
   476  		wantErr                bool
   477  		wantMessageErr         string
   478  		wantSessionValuesEmpty bool
   479  	}{
   480  		{
   481  			name:   "no cachekey found/nothing deleted",
   482  			fields: fields{},
   483  			args: args{
   484  				ctx:     context.Background(),
   485  				session: web.EmptySession(),
   486  			},
   487  			wantErr:                true,
   488  			wantMessageErr:         "cache entry not found",
   489  			wantSessionValuesEmpty: false,
   490  		},
   491  		{
   492  			name:   "deleted an entry",
   493  			fields: fields{},
   494  			args: args{
   495  				ctx: context.Background(),
   496  				session: web.EmptySession().Store(
   497  					application.CartSessionCacheCacheKeyPrefix+"cart__guest_cart_id",
   498  					application.CachedCartEntry{IsInvalid: false},
   499  				),
   500  			},
   501  			wantErr:                false,
   502  			wantMessageErr:         "",
   503  			wantSessionValuesEmpty: true,
   504  		},
   505  	}
   506  
   507  	for _, tt := range tests {
   508  		t.Run(tt.name, func(t *testing.T) {
   509  			c := &application.CartSessionCache{}
   510  			c.Inject(flamingo.NullLogger{}, nil, nil)
   511  
   512  			err := c.DeleteAll(tt.args.ctx, tt.args.session)
   513  
   514  			if (err != nil) != tt.wantErr {
   515  				t.Errorf("CartSessionCache.DeleteAll() error = %v, wantErr %v", err, tt.wantErr)
   516  
   517  				return
   518  			}
   519  
   520  			if err != nil && err.Error() != tt.wantMessageErr {
   521  				t.Errorf("Error doesn't match - error = %v, wantMessageErr %v", err, tt.wantMessageErr)
   522  			}
   523  
   524  			if tt.wantSessionValuesEmpty == true {
   525  				if len(tt.args.session.Keys()) > 0 {
   526  					t.Error("Session Values should have been emptied, but aren't")
   527  				}
   528  			}
   529  		})
   530  	}
   531  }
   532  
   533  func getFixtureCartForTest(t *testing.T) *cart.Cart {
   534  	t.Helper()
   535  	item := cart.Item{
   536  		ID:                "1",
   537  		ExternalReference: "1ext",
   538  		Qty:               2,
   539  		SinglePriceGross:  domain.NewFromInt(2050, 100, "EUR"),
   540  		SinglePriceNet:    domain.NewFromInt(2050, 100, "EUR"),
   541  	}
   542  
   543  	delivery := cart.Delivery{DeliveryInfo: cart.DeliveryInfo{Code: "code"}, Cartitems: []cart.Item{item}}
   544  	cartResult := &cart.Cart{ID: "1", EntityID: "1", DefaultCurrency: "EUR", Deliveries: []cart.Delivery{delivery}}
   545  
   546  	return cartResult
   547  }