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 }