@@ -390,7 +390,6 @@ pub fn replace_banner_product(
390
390
context : & Cluster ,
391
391
) -> Result < Response , Error > {
392
392
let mut all_notification_cookies = Notifications :: get_viewed ( cookies) ;
393
-
394
393
let current_notification_cookie = all_notification_cookies. iter ( ) . position ( |x| x. id == id) ;
395
394
396
395
match current_notification_cookie {
@@ -408,8 +407,8 @@ pub fn replace_banner_product(
408
407
409
408
Notifications :: update_viewed ( & all_notification_cookies, cookies) ;
410
409
411
- // Get the notification that triggered this call.
412
- // Guaranteed to exist since it built the component that called this, so this is safe to unwrap .
410
+ // Get the notification that triggered this call..
411
+ // unwrap notifications if fine since we should panic if this is missing .
413
412
let last_notification = context
414
413
. notifications
415
414
. as_ref ( )
@@ -424,11 +423,15 @@ pub fn replace_banner_product(
424
423
. into_iter ( )
425
424
. filter ( |n : & Notification | -> bool {
426
425
let n = n. clone ( ) . set_viewed ( n. id == id) ;
427
- Notification :: product_filter (
428
- & n,
429
- last_notification. clone ( ) . unwrap ( ) . level . clone ( ) ,
430
- deployment_id. clone ( ) ,
431
- )
426
+ if last_notification. clone ( ) . is_none ( ) {
427
+ return false ;
428
+ } else {
429
+ Notification :: product_filter (
430
+ & n,
431
+ last_notification. clone ( ) . unwrap ( ) . level . clone ( ) ,
432
+ deployment_id. clone ( ) ,
433
+ )
434
+ }
432
435
} )
433
436
. next ( ) ,
434
437
_ => None ,
@@ -519,3 +522,188 @@ pub fn routes() -> Vec<Route> {
519
522
pub async fn migrate ( pool : & PgPool ) -> anyhow:: Result < ( ) > {
520
523
Ok ( sqlx:: migrate!( "./migrations" ) . run ( pool) . await ?)
521
524
}
525
+
526
+ #[ cfg( test) ]
527
+ mod test {
528
+ use super :: * ;
529
+ use crate :: components:: sections:: footers:: MarketingFooter ;
530
+ use crate :: guards:: Cluster ;
531
+ use rocket:: fairing:: AdHoc ;
532
+ use rocket:: http:: Cookie ;
533
+ use rocket:: local:: asynchronous:: Client ;
534
+
535
+ #[ sqlx:: test]
536
+ async fn test_remove_modal ( ) {
537
+ let rocket = rocket:: build ( ) . mount ( "/" , routes ( ) ) ;
538
+ let client = Client :: untracked ( rocket) . await . unwrap ( ) ;
539
+
540
+ let cookie = vec ! [
541
+ NotificationCookie {
542
+ id: "1" . to_string( ) ,
543
+ time_viewed: Some ( chrono:: Utc :: now( ) - chrono:: Duration :: days( 1 ) ) ,
544
+ time_modal_viewed: Some ( chrono:: Utc :: now( ) - chrono:: Duration :: days( 1 ) ) ,
545
+ } ,
546
+ NotificationCookie {
547
+ id: "2" . to_string( ) ,
548
+ time_viewed: None ,
549
+ time_modal_viewed: None ,
550
+ } ,
551
+ ] ;
552
+
553
+ let response = client
554
+ . get ( "/notifications/product/modal/remove_modal?id=1" )
555
+ . private_cookie ( Cookie :: new ( "session" , Notifications :: safe_serialize_session ( & cookie) ) )
556
+ . dispatch ( )
557
+ . await ;
558
+
559
+ let time_modal_viewed = Notifications :: get_viewed ( response. cookies ( ) )
560
+ . get ( 0 )
561
+ . unwrap ( )
562
+ . time_modal_viewed ;
563
+
564
+ // Update modal view time for existing notification cookie
565
+ assert_eq ! ( time_modal_viewed. is_some( ) , true ) ;
566
+
567
+ let response = client
568
+ . get ( "/notifications/product/modal/remove_modal?id=3" )
569
+ . private_cookie ( Cookie :: new ( "session" , Notifications :: safe_serialize_session ( & cookie) ) )
570
+ . dispatch ( )
571
+ . await ;
572
+
573
+ let time_modal_viewed = Notifications :: get_viewed ( response. cookies ( ) )
574
+ . get ( 0 )
575
+ . unwrap ( )
576
+ . time_modal_viewed ;
577
+
578
+ // Update modal view time for new notification cookie
579
+ assert_eq ! ( time_modal_viewed. is_some( ) , true ) ;
580
+ }
581
+
582
+ #[ sqlx:: test]
583
+ async fn test_remove_banner_product ( ) {
584
+ let rocket = rocket:: build ( ) . mount ( "/" , routes ( ) ) ;
585
+ let client = Client :: untracked ( rocket) . await . unwrap ( ) ;
586
+
587
+ let cookie = vec ! [
588
+ NotificationCookie {
589
+ id: "1" . to_string( ) ,
590
+ time_viewed: Some ( chrono:: Utc :: now( ) - chrono:: Duration :: days( 1 ) ) ,
591
+ time_modal_viewed: Some ( chrono:: Utc :: now( ) - chrono:: Duration :: days( 1 ) ) ,
592
+ } ,
593
+ NotificationCookie {
594
+ id: "2" . to_string( ) ,
595
+ time_viewed: None ,
596
+ time_modal_viewed: Some ( chrono:: Utc :: now( ) - chrono:: Duration :: days( 1 ) ) ,
597
+ } ,
598
+ ] ;
599
+
600
+ let response = client
601
+ . get ( "/notifications/product/remove_banner?id=1&target=ajskghjfbs" )
602
+ . private_cookie ( Cookie :: new ( "session" , Notifications :: safe_serialize_session ( & cookie) ) )
603
+ . dispatch ( )
604
+ . await ;
605
+
606
+ let time_viewed = Notifications :: get_viewed ( response. cookies ( ) )
607
+ . get ( 0 )
608
+ . unwrap ( )
609
+ . time_viewed ;
610
+
611
+ // Update view time for existing notification cookie
612
+ assert_eq ! ( time_viewed. is_some( ) , true ) ;
613
+
614
+ let response = client
615
+ . get ( "/notifications/product/remove_banner?id=3&target=ajfadghs" )
616
+ . private_cookie ( Cookie :: new ( "session" , Notifications :: safe_serialize_session ( & cookie) ) )
617
+ . dispatch ( )
618
+ . await ;
619
+
620
+ let time_viewed = Notifications :: get_viewed ( response. cookies ( ) )
621
+ . get ( 0 )
622
+ . unwrap ( )
623
+ . time_viewed ;
624
+
625
+ // Update view time for new notification cookie
626
+ assert_eq ! ( time_viewed. is_some( ) , true ) ;
627
+ }
628
+
629
+ #[ sqlx:: test]
630
+ async fn test_replace_banner_product ( ) {
631
+ let notification1 = Notification :: new ( "Test notification 1" )
632
+ . set_level ( & NotificationLevel :: ProductMedium )
633
+ . set_deployment ( "1" ) ;
634
+ let notification2 = Notification :: new ( "Test notification 2" )
635
+ . set_level ( & NotificationLevel :: ProductMedium )
636
+ . set_deployment ( "1" ) ;
637
+ let _notification3 = Notification :: new ( "Test notification 3" )
638
+ . set_level ( & NotificationLevel :: ProductMedium )
639
+ . set_deployment ( "2" ) ;
640
+ let _notification4 = Notification :: new ( "Test notification 4" ) . set_level ( & NotificationLevel :: ProductMedium ) ;
641
+ let _notification5 = Notification :: new ( "Test notification 5" ) . set_level ( & NotificationLevel :: ProductMarketing ) ;
642
+
643
+ let rocket = rocket:: build ( )
644
+ . attach ( AdHoc :: on_request ( "request" , |req, _| {
645
+ Box :: pin ( async {
646
+ req. local_cache ( || Cluster {
647
+ pool : None ,
648
+ context : Context {
649
+ user : models:: User :: default ( ) ,
650
+ cluster : models:: Cluster :: default ( ) ,
651
+ dropdown_nav : StaticNav { links : vec ! [ ] } ,
652
+ product_left_nav : StaticNav { links : vec ! [ ] } ,
653
+ marketing_footer : MarketingFooter :: new ( ) . render_once ( ) . unwrap ( ) ,
654
+ head_items : None ,
655
+ } ,
656
+ notifications : Some ( vec ! [
657
+ Notification :: new( "Test notification 1" )
658
+ . set_level( & NotificationLevel :: ProductMedium )
659
+ . set_deployment( "1" ) ,
660
+ Notification :: new( "Test notification 2" )
661
+ . set_level( & NotificationLevel :: ProductMedium )
662
+ . set_deployment( "1" ) ,
663
+ Notification :: new( "Test notification 3" )
664
+ . set_level( & NotificationLevel :: ProductMedium )
665
+ . set_deployment( "2" ) ,
666
+ Notification :: new( "Test notification 4" ) . set_level( & NotificationLevel :: ProductMedium ) ,
667
+ Notification :: new( "Test notification 5" ) . set_level( & NotificationLevel :: ProductMarketing ) ,
668
+ ] ) ,
669
+ } ) ;
670
+ } )
671
+ } ) )
672
+ . mount ( "/" , routes ( ) ) ;
673
+
674
+ let client = Client :: tracked ( rocket) . await . unwrap ( ) ;
675
+
676
+ let response = client
677
+ . get ( format ! (
678
+ "/notifications/product/replace_banner?id={}&deployment_id=1" ,
679
+ notification1. id
680
+ ) )
681
+ . dispatch ( )
682
+ . await ;
683
+
684
+ let body = response. into_string ( ) . await . unwrap ( ) ;
685
+ let rsp_contains_next_notification = body. contains ( "Test notification 2" ) ;
686
+
687
+ // Ensure the banner is replaced with next notification of same type
688
+ assert_eq ! ( rsp_contains_next_notification, true ) ;
689
+
690
+ let response = client
691
+ . get ( format ! (
692
+ "/notifications/product/replace_banner?id={}&deployment_id=1" ,
693
+ notification2. id
694
+ ) )
695
+ . dispatch ( )
696
+ . await ;
697
+
698
+ let body = response. into_string ( ) . await . unwrap ( ) ;
699
+ let rsp_contains_next_notification_3 = body. contains ( "Test notification 3" ) ;
700
+ let rsp_contains_next_notification_4 = body. contains ( "Test notification 4" ) ;
701
+ let rsp_contains_next_notification_5 = body. contains ( "Test notification 5" ) ;
702
+
703
+ // Ensure the next notification is not found since none match deployment id or level
704
+ assert_eq ! (
705
+ rsp_contains_next_notification_3 && rsp_contains_next_notification_4 && rsp_contains_next_notification_5,
706
+ false
707
+ ) ;
708
+ }
709
+ }
0 commit comments