@@ -904,3 +904,105 @@ test.skip("[TYPE ONLY] can narrow validation type to success", () => {
904904 }
905905 }
906906} ) ;
907+
908+ test ( "can validate files" , async ( ) => {
909+ const spy = jest . fn ( ) ;
910+
911+ const Schema = z . object ( {
912+ myFile : z . instanceof ( File ) . refine ( ( file ) => {
913+ spy ( file . type ) ;
914+ return file . type === "image/png" ;
915+ } , "Only .png images are allowed" ) ,
916+ } ) ;
917+
918+ function Test ( ) {
919+ const zo = useZorm ( "form" , Schema ) ;
920+
921+ return (
922+ < form ref = { zo . ref } data-testid = "form" >
923+ < input
924+ data-testid = "file"
925+ type = "file"
926+ name = { zo . fields . myFile ( ) }
927+ />
928+
929+ { zo . errors . myFile ( ( e ) => (
930+ < div data-testid = "error" > { e . message } </ div >
931+ ) ) }
932+ </ form >
933+ ) ;
934+ }
935+
936+ render ( < Test /> ) ;
937+
938+ const file = new File ( [ "(⌐□_□)" ] , "chucknorris.txt" , {
939+ type : "text/plain" ,
940+ } ) ;
941+
942+ const fileInput = screen . getByTestId ( "file" ) as HTMLInputElement ;
943+ await userEvent . upload ( fileInput , file ) ;
944+ fireEvent . submit ( screen . getByTestId ( "form" ) ) ;
945+
946+ {
947+ // TEMP TESTS
948+ const form = screen . getByTestId ( "form" ) as HTMLFormElement ;
949+ expect ( fileInput . files ?. [ 0 ] ?. name ) . toBe ( "chucknorris.txt" ) ;
950+ const formData = new FormData ( form ) ;
951+ expect ( formData . get ( "myFile" ) ) . toBeInstanceOf ( File ) ;
952+ const formFile = formData . get ( "myFile" ) as File ;
953+
954+ // XXX Bug in jsdom or react testing lib?
955+ // FormData cannot read file from the form.
956+ expect ( formFile . name ) . toBe ( "chucknorris.txt" ) ;
957+ }
958+
959+ expect ( spy ) . toHaveBeenCalledWith ( "text/plain" ) ;
960+
961+ expect ( screen . queryByTestId ( "error" ) ) . toHaveTextContent (
962+ "Only .png images are allowed" ,
963+ ) ;
964+ } ) ;
965+
966+ test ( "can submit files" , async ( ) => {
967+ const spy = jest . fn ( ) ;
968+
969+ const Schema = z . object ( {
970+ myFile : z . instanceof ( File ) . refine ( ( file ) => {
971+ return file . type === "image/png" ;
972+ } , "Only .png images are allowed" ) ,
973+ } ) ;
974+
975+ function Test ( ) {
976+ const zo = useZorm ( "form" , Schema , {
977+ onValidSubmit ( e ) {
978+ spy ( e . data . myFile . name ) ;
979+ } ,
980+ } ) ;
981+
982+ return (
983+ < form ref = { zo . ref } data-testid = "form" >
984+ < input
985+ data-testid = "file"
986+ type = "file"
987+ name = { zo . fields . myFile ( ) }
988+ />
989+
990+ { zo . errors . myFile ( ( e ) => (
991+ < div data-testid = "error" > { e . message } </ div >
992+ ) ) }
993+ </ form >
994+ ) ;
995+ }
996+
997+ render ( < Test /> ) ;
998+
999+ const file = new File ( [ "(⌐□_□)" ] , "chucknorris.png" , {
1000+ type : "image/png" ,
1001+ } ) ;
1002+
1003+ const fileInput = screen . getByTestId ( "file" ) as HTMLInputElement ;
1004+ await userEvent . upload ( fileInput , file ) ;
1005+ fireEvent . submit ( screen . getByTestId ( "form" ) ) ;
1006+
1007+ expect ( spy ) . toHaveBeenCalledWith ( "text/plain" ) ;
1008+ } ) ;
0 commit comments