@@ -562,7 +562,7 @@ pub struct RequestResultArray {
562562 pub results : Vec < RequestResultData > ,
563563}
564564
565- #[ derive( Debug , Clone , Serialize , Deserialize ) ]
565+ #[ derive( Debug , Clone , Serialize , Deserialize , PartialEq ) ]
566566#[ serde( untagged) ]
567567pub enum DBResponsePrimitive {
568568 Null ,
@@ -601,3 +601,295 @@ impl Display for DBResponseValue {
601601 write ! ( f, "{}" , str )
602602 }
603603}
604+
605+ #[ cfg( test) ]
606+ mod tests {
607+ use super :: * ;
608+ use chrono:: { TimeZone , Utc , Timelike } ;
609+ use anyhow:: Result ;
610+
611+ #[ test]
612+ fn test_transform_value_datetime_to_time ( ) {
613+ let dt = Utc . with_ymd_and_hms ( 2024 , 1 , 1 , 12 , 30 , 15 )
614+ . unwrap ( )
615+ . with_nanosecond ( 123_000_000 )
616+ . unwrap ( ) ;
617+ let value = DBResponseValue :: DateTime ( dt) ;
618+ let result = transform_value ( value, "time" ) ;
619+
620+ assert_eq ! (
621+ result,
622+ DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123Z" . to_string( ) )
623+ ) ;
624+ }
625+
626+ #[ test]
627+ fn test_transform_value_datetime_empty_type ( ) {
628+ let dt = Utc . with_ymd_and_hms ( 2024 , 1 , 1 , 12 , 30 , 15 )
629+ . unwrap ( )
630+ . with_nanosecond ( 123_000_000 )
631+ . unwrap ( ) ;
632+ let value = DBResponseValue :: DateTime ( dt) ;
633+ let result = transform_value ( value, "" ) ;
634+
635+ assert_eq ! (
636+ result,
637+ DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123Z" . to_string( ) )
638+ ) ;
639+ }
640+
641+ #[ test]
642+ fn test_transform_value_string_to_time_valid_rfc3339 ( ) {
643+ let value = DBResponseValue :: Primitive ( DBResponsePrimitive :: String (
644+ "2024-01-01T12:30:15.123Z" . to_string ( ) ,
645+ ) ) ;
646+ let result = transform_value ( value, "time" ) ;
647+
648+ assert_eq ! (
649+ result,
650+ DBResponsePrimitive :: String ( "2024-01-01T12:30:15.123Z" . to_string( ) )
651+ ) ;
652+ }
653+
654+ #[ test]
655+ fn test_transform_value_string_to_time_invalid_rfc3339 ( ) {
656+ let value = DBResponseValue :: Primitive ( DBResponsePrimitive :: String (
657+ "invalid-date" . to_string ( ) ,
658+ ) ) ;
659+ let result = transform_value ( value, "time" ) ;
660+
661+ assert_eq ! (
662+ result,
663+ DBResponsePrimitive :: String ( "invalid-date" . to_string( ) )
664+ ) ;
665+ }
666+
667+ #[ test]
668+ fn test_transform_value_primitive_string_type_not_time ( ) {
669+ let value = DBResponseValue :: Primitive ( DBResponsePrimitive :: String (
670+ "some-string" . to_string ( ) ,
671+ ) ) ;
672+ let result = transform_value ( value, "other" ) ;
673+
674+ assert_eq ! (
675+ result,
676+ DBResponsePrimitive :: String ( "some-string" . to_string( ) )
677+ ) ;
678+ }
679+
680+ #[ test]
681+ fn test_transform_value_object ( ) {
682+ let obj_value = DBResponsePrimitive :: String ( "object-value" . to_string ( ) ) ;
683+ let value = DBResponseValue :: Object { value : obj_value. clone ( ) } ;
684+ let result = transform_value ( value, "time" ) ;
685+
686+ assert_eq ! ( result, obj_value) ;
687+ }
688+
689+ #[ test]
690+ fn test_transform_value_fallback_to_null ( ) {
691+ let value = DBResponseValue :: DateTime ( Utc :: now ( ) ) ;
692+ let result = transform_value ( value, "unknown" ) ;
693+
694+ assert_eq ! ( result, DBResponsePrimitive :: Null ) ;
695+ }
696+
697+ #[ test]
698+ fn test_get_date_range_value_valid_range ( ) -> Result < ( ) > {
699+ let time_dimensions = vec ! [ QueryTimeDimension {
700+ dimension: "some-dim" . to_string( ) ,
701+ date_range: Some ( vec![
702+ "2024-01-01T00:00:00Z" . to_string( ) ,
703+ "2024-01-31T23:59:59Z" . to_string( ) ,
704+ ] ) ,
705+ compare_date_range: None ,
706+ granularity: None ,
707+ } ] ;
708+
709+ let result = get_date_range_value ( Some ( & time_dimensions) ) ?;
710+ assert_eq ! (
711+ result,
712+ DBResponsePrimitive :: String ( "2024-01-01T00:00:00Z - 2024-01-31T23:59:59Z" . to_string( ) )
713+ ) ;
714+ Ok ( ( ) )
715+ }
716+
717+ #[ test]
718+ fn test_get_date_range_value_no_time_dimensions ( ) {
719+ let result = get_date_range_value ( None ) ;
720+ assert ! ( result. is_err( ) ) ;
721+ assert_eq ! (
722+ result. unwrap_err( ) . to_string( ) ,
723+ "QueryTimeDimension should be specified for the compare date range query."
724+ ) ;
725+ }
726+
727+ #[ test]
728+ fn test_get_date_range_value_empty_time_dimensions ( ) {
729+ let time_dimensions: Vec < QueryTimeDimension > = vec ! [ ] ;
730+
731+ let result = get_date_range_value ( Some ( & time_dimensions) ) ;
732+ assert ! ( result. is_err( ) ) ;
733+ assert_eq ! (
734+ result. unwrap_err( ) . to_string( ) ,
735+ "No time dimension provided."
736+ ) ;
737+ }
738+
739+ #[ test]
740+ fn test_get_date_range_value_missing_date_range ( ) {
741+ let time_dimensions = vec ! [ QueryTimeDimension {
742+ dimension: "dim" . to_string( ) ,
743+ date_range: None ,
744+ compare_date_range: None ,
745+ granularity: None ,
746+ } ] ;
747+
748+ let result = get_date_range_value ( Some ( & time_dimensions) ) ;
749+ assert ! ( result. is_err( ) ) ;
750+ assert_eq ! (
751+ result. unwrap_err( ) . to_string( ) ,
752+ "Inconsistent QueryTimeDimension configuration: dateRange required."
753+ ) ;
754+ }
755+
756+ #[ test]
757+ fn test_get_date_range_value_single_date_range ( ) {
758+ let time_dimensions = vec ! [ QueryTimeDimension {
759+ dimension: "dim" . to_string( ) ,
760+ date_range: Some ( vec![ "2024-01-01T00:00:00Z" . to_string( ) ] ) ,
761+ compare_date_range: None ,
762+ granularity: None ,
763+ } ] ;
764+
765+ let result = get_date_range_value ( Some ( & time_dimensions) ) ;
766+ assert ! ( result. is_err( ) ) ;
767+ assert_eq ! (
768+ result. unwrap_err( ) . to_string( ) ,
769+ "Inconsistent dateRange configuration for the compare date range query: 2024-01-01T00:00:00Z"
770+ ) ;
771+ }
772+
773+ #[ test]
774+ fn test_get_blending_query_key_valid_granularity ( ) -> Result < ( ) > {
775+ let time_dimensions = vec ! [ QueryTimeDimension {
776+ dimension: "dim" . to_string( ) ,
777+ granularity: Some ( "day" . to_string( ) ) ,
778+ date_range: None ,
779+ compare_date_range: None ,
780+ } ] ;
781+
782+ let result = get_blending_query_key ( Some ( & time_dimensions) ) ?;
783+ assert_eq ! ( result, "time.day" ) ;
784+ Ok ( ( ) )
785+ }
786+
787+ #[ test]
788+ fn test_get_blending_query_key_no_time_dimensions ( ) {
789+ let result = get_blending_query_key ( None ) ;
790+ assert ! ( result. is_err( ) ) ;
791+ assert_eq ! (
792+ result. unwrap_err( ) . to_string( ) ,
793+ "QueryTimeDimension should be specified for the blending query."
794+ ) ;
795+ }
796+
797+ #[ test]
798+ fn test_get_blending_query_key_empty_time_dimensions ( ) {
799+ let time_dimensions: Vec < QueryTimeDimension > = vec ! [ ] ;
800+
801+ let result = get_blending_query_key ( Some ( & time_dimensions) ) ;
802+ assert ! ( result. is_err( ) ) ;
803+ assert_eq ! (
804+ result. unwrap_err( ) . to_string( ) ,
805+ "QueryTimeDimension should be specified for the blending query."
806+ ) ;
807+ }
808+
809+ #[ test]
810+ fn test_get_blending_query_key_missing_granularity ( ) {
811+ let time_dimensions = vec ! [ QueryTimeDimension {
812+ dimension: "dim" . to_string( ) ,
813+ granularity: None ,
814+ date_range: None ,
815+ compare_date_range: None ,
816+ } ] ;
817+
818+ let result = get_blending_query_key ( Some ( & time_dimensions) ) ;
819+ assert ! ( result. is_err( ) ) ;
820+ assert_eq ! (
821+ result. unwrap_err( ) . to_string( ) ,
822+ format!(
823+ "Inconsistent QueryTimeDimension configuration for the blending query, granularity required: {:?}" ,
824+ QueryTimeDimension {
825+ dimension: "dim" . to_string( ) ,
826+ granularity: None ,
827+ date_range: None ,
828+ compare_date_range: None ,
829+ }
830+ )
831+ ) ;
832+ }
833+
834+ #[ test]
835+ fn test_get_blending_response_key_valid_dimension_and_granularity ( ) -> Result < ( ) > {
836+ let time_dimensions = vec ! [ QueryTimeDimension {
837+ dimension: "orders.created_at" . to_string( ) ,
838+ granularity: Some ( "day" . to_string( ) ) ,
839+ date_range: None ,
840+ compare_date_range: None ,
841+ } ] ;
842+
843+ let result = get_blending_response_key ( Some ( & time_dimensions) ) ?;
844+ assert_eq ! ( result, "orders.created_at.day" ) ;
845+ Ok ( ( ) )
846+ }
847+
848+ #[ test]
849+ fn test_get_blending_response_key_no_time_dimensions ( ) {
850+ let result = get_blending_response_key ( None ) ;
851+ assert ! ( result. is_err( ) ) ;
852+ assert_eq ! (
853+ result. unwrap_err( ) . to_string( ) ,
854+ "QueryTimeDimension should be specified for the blending query."
855+ ) ;
856+ }
857+
858+ #[ test]
859+ fn test_get_blending_response_key_empty_time_dimensions ( ) {
860+ let time_dimensions: Vec < QueryTimeDimension > = vec ! [ ] ;
861+
862+ let result = get_blending_response_key ( Some ( & time_dimensions) ) ;
863+ assert ! ( result. is_err( ) ) ;
864+ assert_eq ! (
865+ result. unwrap_err( ) . to_string( ) ,
866+ "QueryTimeDimension should be specified for the blending query."
867+ ) ;
868+ }
869+
870+ #[ test]
871+ fn test_get_blending_response_key_missing_granularity ( ) {
872+ let time_dimensions = vec ! [ QueryTimeDimension {
873+ dimension: "orders.created_at" . to_string( ) ,
874+ granularity: None ,
875+ date_range: None ,
876+ compare_date_range: None ,
877+ } ] ;
878+
879+ let result = get_blending_response_key ( Some ( & time_dimensions) ) ;
880+ assert ! ( result. is_err( ) ) ;
881+ assert_eq ! (
882+ result. unwrap_err( ) . to_string( ) ,
883+ format!(
884+ "Inconsistent QueryTimeDimension configuration for the blending query, granularity required: {:?}" ,
885+ QueryTimeDimension {
886+ dimension: "orders.created_at" . to_string( ) ,
887+ granularity: None ,
888+ date_range: None ,
889+ compare_date_range: None ,
890+ }
891+ )
892+ ) ;
893+ }
894+
895+ }
0 commit comments