@@ -390,7 +390,6 @@ pub fn replace_banner_product(
390390context : & Cluster ,
391391) ->Result < Response , Error > {
392392let mut all_notification_cookies =Notifications :: get_viewed ( cookies) ;
393-
394393let current_notification_cookie = all_notification_cookies. iter ( ) . position ( |x| x. id == id) ;
395394
396395match current_notification_cookie{
@@ -408,8 +407,8 @@ pub fn replace_banner_product(
408407
409408Notifications :: update_viewed ( & all_notification_cookies, cookies) ;
410409
411- // Get the notification that triggered this call.
412- //Guaranteed to exist sinceit built the component that called this, so this issafe to unwrap .
410+ // Get the notification that triggered this call..
411+ //unwrap notifications if fine sincewe should panic if this ismissing .
413412let last_notification = context
414413. notifications
415414. as_ref ( )
@@ -424,11 +423,15 @@ pub fn replace_banner_product(
424423. into_iter ( )
425424. filter ( |n : & Notification | ->bool {
426425let 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+ }
432435} )
433436. next ( ) ,
434437 _ =>None ,
@@ -519,3 +522,188 @@ pub fn routes() -> Vec<Route> {
519522pub async fn migrate ( pool : & PgPool ) -> anyhow:: Result < ( ) > {
520523Ok ( sqlx:: migrate!( "./migrations" ) . run ( pool) . await ?)
521524}
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+ }