@@ -658,3 +658,220 @@ fn template_pycompat_filters() {
658658 ) ;
659659 assert_eq ! ( got, expected) ;
660660}
661+
662+ #[ test]
663+ fn template_custom_filters_error_handling ( ) {
664+ let wrk = Workdir :: new ( "template_custom_filters_error" ) ;
665+ wrk. create (
666+ "data.csv" ,
667+ vec ! [
668+ svec![ "value" , "number" ] ,
669+ svec![ "abc" , "123.456" ] ,
670+ svec![ "def" , "not_a_number" ] ,
671+ ] ,
672+ ) ;
673+
674+ let mut cmd = wrk. command ( "template" ) ;
675+ cmd. arg ( "--template" )
676+ . arg ( concat ! (
677+ "format_float: {{number|format_float(2)}}\n " ,
678+ "human_count: {{number|human_count}}\n " ,
679+ "human_float_count: {{number|human_float_count}}\n " ,
680+ "round_banker: {{number|round_banker(3)}}\n " ,
681+ "\n "
682+ ) )
683+ . arg ( "--customfilter-error" )
684+ . arg ( "ERROR" )
685+ . arg ( "data.csv" ) ;
686+
687+ let got: String = wrk. stdout ( & mut cmd) ;
688+ let expected = concat ! (
689+ "format_float: 123.46\n " ,
690+ "human_count: ERROR\n " ,
691+ "human_float_count: 123.456\n " ,
692+ "round_banker: 123.456\n " ,
693+ "format_float: ERROR\n " ,
694+ "human_count: ERROR\n " ,
695+ "human_float_count: ERROR\n " ,
696+ "round_banker: ERROR"
697+ ) ;
698+ assert_eq ! ( got, expected) ;
699+ }
700+
701+ #[ test]
702+ fn template_str_to_bool_filter ( ) {
703+ let wrk = Workdir :: new ( "template_str_to_bool" ) ;
704+ wrk. create (
705+ "data.csv" ,
706+ vec ! [
707+ svec![ "value" ] ,
708+ svec![ "true" ] ,
709+ svec![ "1" ] ,
710+ svec![ "yes" ] ,
711+ svec![ "t" ] ,
712+ svec![ "y" ] ,
713+ svec![ "false" ] ,
714+ svec![ "0" ] ,
715+ svec![ "no" ] ,
716+ ] ,
717+ ) ;
718+
719+ let mut cmd = wrk. command ( "template" ) ;
720+ cmd. arg ( "--template" )
721+ . arg ( "{{value|str_to_bool}}\n \n " )
722+ . arg ( "data.csv" ) ;
723+
724+ let got: String = wrk. stdout ( & mut cmd) ;
725+ let expected =
726+ concat ! ( "true\n " , "true\n " , "true\n " , "true\n " , "true\n " , "false\n " , "false\n " , "false" ) ;
727+ assert_eq ! ( got, expected) ;
728+ }
729+
730+ #[ test]
731+ fn template_substr_filter ( ) {
732+ let wrk = Workdir :: new ( "template_substr" ) ;
733+ wrk. create (
734+ "data.csv" ,
735+ vec ! [ svec![ "text" ] , svec![ "Hello World" ] , svec![ "Testing 123" ] ] ,
736+ ) ;
737+
738+ let mut cmd = wrk. command ( "template" ) ;
739+ cmd. arg ( "--template" )
740+ . arg ( concat ! (
741+ "start_only: {{text|substr(0)}}\n " ,
742+ "start_end: {{text|substr(0,5)}}\n " ,
743+ "middle: {{text|substr(6,11)}}\n " ,
744+ "invalid: {{text|substr(100)}}\n " ,
745+ "\n "
746+ ) )
747+ . arg ( "--customfilter-error" )
748+ . arg ( "ERROR" )
749+ . arg ( "data.csv" ) ;
750+
751+ let got: String = wrk. stdout ( & mut cmd) ;
752+ let expected = concat ! (
753+ "start_only: Hello World\n " ,
754+ "start_end: Hello\n " ,
755+ "middle: World\n " ,
756+ "invalid: ERROR\n " ,
757+ "start_only: Testing 123\n " ,
758+ "start_end: Testi\n " ,
759+ "middle: g 123\n " ,
760+ "invalid: ERROR"
761+ ) ;
762+ assert_eq ! ( got, expected) ;
763+ }
764+
765+ #[ test]
766+ fn template_lookup_filter_simple ( ) {
767+ let wrk = Workdir :: new ( "template_lookup" ) ;
768+
769+ // Create a lookup table CSV
770+ wrk. create (
771+ "lookup.csv" ,
772+ vec ! [
773+ svec![ "id" , "name" , "description" ] ,
774+ svec![ "1" , "apple" , "A red fruit" ] ,
775+ svec![ "2" , "banana" , "A yellow fruit" ] ,
776+ svec![ "3" , "orange" , "A citrus fruit" ] ,
777+ ] ,
778+ ) ;
779+
780+ // Create main data CSV
781+ wrk. create (
782+ "data.csv" ,
783+ vec ! [
784+ svec![ "product_id" , "quantity" ] ,
785+ svec![ "1" , "5" ] ,
786+ svec![ "2" , "3" ] ,
787+ svec![ "4" , "1" ] , // Invalid ID to test error handling
788+ ] ,
789+ ) ;
790+
791+ let mut cmd = wrk. command ( "template" ) ;
792+ cmd. arg ( "--template" )
793+ . arg ( concat ! (
794+ "{% set result = register_lookup('products', 'lookup.csv') %}" ,
795+ "{% if result %}" ,
796+ "{{product_id}}: {{product_id|lookup('products', 'id', 'name')}} - \
797+ {{product_id|lookup('products', 'id', 'description')}}\n ",
798+ "{% else %}" ,
799+ "Error: Failed to register lookup table 'products' {{ result.err }} \n " ,
800+ "{% endif %}"
801+ ) )
802+ . arg ( "--customfilter-error" )
803+ . arg ( "<not found>" )
804+ . arg ( "data.csv" ) ;
805+
806+ wrk. assert_success ( & mut cmd) ;
807+
808+ let got: String = wrk. stdout ( & mut cmd) ;
809+ let expected = concat ! (
810+ "1: apple - A red fruit\n " ,
811+ "2: banana - A yellow fruit\n " ,
812+ "4: <not found> - <not found>"
813+ ) ;
814+ assert_eq ! ( got, expected) ;
815+ }
816+
817+ #[ test]
818+ fn template_lookup_filter_errors ( ) {
819+ let wrk = Workdir :: new ( "template_lookup_errors" ) ;
820+
821+ wrk. create ( "data.csv" , vec ! [ svec![ "id" ] , svec![ "1" ] ] ) ;
822+
823+ // Test missing lookup key
824+ let mut cmd = wrk. command ( "template" ) ;
825+ cmd. arg ( "--template" )
826+ . arg ( "{{id|lookup('', 'name')}}" )
827+ . arg ( "data.csv" ) ;
828+
829+ wrk. assert_success ( & mut cmd) ;
830+
831+ let got: String = wrk. stdout ( & mut cmd) ;
832+ assert ! ( got. contains( "RENDERING ERROR" ) ) ;
833+
834+ // Test missing field name
835+ let mut cmd = wrk. command ( "template" ) ;
836+ cmd. arg ( "--template" )
837+ . arg ( "{{id|lookup('id', '')}}" )
838+ . arg ( "data.csv" ) ;
839+
840+ let got: String = wrk. stdout ( & mut cmd) ;
841+ assert ! ( got. contains( "RENDERING ERROR" ) ) ;
842+
843+ // Test unregistered lookup table
844+ let mut cmd = wrk. command ( "template" ) ;
845+ cmd. arg ( "--template" )
846+ . arg ( "{{id|lookup('id', 'name')}}" )
847+ . arg ( "data.csv" ) ;
848+
849+ let got: String = wrk. stdout ( & mut cmd) ;
850+ assert ! ( got. contains( "RENDERING ERROR" ) ) ;
851+ }
852+
853+ #[ test]
854+ fn template_lookup_register_errors ( ) {
855+ let wrk = Workdir :: new ( "template_lookup_register" ) ;
856+
857+ wrk. create ( "data.csv" , vec ! [ svec![ "id" ] , svec![ "1" ] ] ) ;
858+
859+ // Test non-existent lookup file
860+ let mut cmd = wrk. command ( "template" ) ;
861+ cmd. arg ( "--template" )
862+ . arg ( concat ! (
863+ "{% if register_lookup('test', 'nonexistent.csv') %}\n " ,
864+ "success\n " ,
865+ "{% else %}\n " ,
866+ "failed\n " ,
867+ "{% endif %}"
868+ ) )
869+ . arg ( "data.csv" ) ;
870+
871+ let got: String = wrk. stdout ( & mut cmd) ;
872+ assert_eq ! (
873+ got,
874+ "RENDERING ERROR (1): invalid operation: failed to load lookup table: failed to open \
875+ nonexistent.csv: No such file or directory (os error 2) (in template:1)"
876+ ) ;
877+ }
0 commit comments