@@ -1041,4 +1041,301 @@ pub fn get_users() -> String {
10411041
10421042 drop ( temp_dir) ;
10431043 }
1044+
1045+ // ========== Tests for parsing functions ==========
1046+
1047+ #[ test]
1048+ fn test_parse_openapi_values_single ( ) {
1049+ // Test that single string openapi value parses correctly via AutoRouterInput
1050+ let tokens = quote:: quote!( openapi = "openapi.json" ) ;
1051+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1052+ let openapi = input. openapi . unwrap ( ) ;
1053+ assert_eq ! ( openapi. len( ) , 1 ) ;
1054+ assert_eq ! ( openapi[ 0 ] . value( ) , "openapi.json" ) ;
1055+ }
1056+
1057+ #[ test]
1058+ fn test_parse_openapi_values_array ( ) {
1059+ // Test that array openapi value parses correctly via AutoRouterInput
1060+ let tokens = quote:: quote!( openapi = [ "openapi.json" , "api.json" ] ) ;
1061+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1062+ let openapi = input. openapi . unwrap ( ) ;
1063+ assert_eq ! ( openapi. len( ) , 2 ) ;
1064+ assert_eq ! ( openapi[ 0 ] . value( ) , "openapi.json" ) ;
1065+ assert_eq ! ( openapi[ 1 ] . value( ) , "api.json" ) ;
1066+ }
1067+
1068+ #[ test]
1069+ fn test_validate_server_url_valid_http ( ) {
1070+ let lit = LitStr :: new ( "http://localhost:3000" , Span :: call_site ( ) ) ;
1071+ let result = validate_server_url ( & lit) ;
1072+ assert ! ( result. is_ok( ) ) ;
1073+ assert_eq ! ( result. unwrap( ) , "http://localhost:3000" ) ;
1074+ }
1075+
1076+ #[ test]
1077+ fn test_validate_server_url_valid_https ( ) {
1078+ let lit = LitStr :: new ( "https://api.example.com" , Span :: call_site ( ) ) ;
1079+ let result = validate_server_url ( & lit) ;
1080+ assert ! ( result. is_ok( ) ) ;
1081+ assert_eq ! ( result. unwrap( ) , "https://api.example.com" ) ;
1082+ }
1083+
1084+ #[ test]
1085+ fn test_validate_server_url_invalid ( ) {
1086+ let lit = LitStr :: new ( "ftp://example.com" , Span :: call_site ( ) ) ;
1087+ let result = validate_server_url ( & lit) ;
1088+ assert ! ( result. is_err( ) ) ;
1089+ }
1090+
1091+ #[ test]
1092+ fn test_validate_server_url_no_scheme ( ) {
1093+ let lit = LitStr :: new ( "example.com" , Span :: call_site ( ) ) ;
1094+ let result = validate_server_url ( & lit) ;
1095+ assert ! ( result. is_err( ) ) ;
1096+ }
1097+
1098+ #[ test]
1099+ fn test_auto_router_input_parse_dir_only ( ) {
1100+ let tokens = quote:: quote!( dir = "api" ) ;
1101+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1102+ assert_eq ! ( input. dir. unwrap( ) . value( ) , "api" ) ;
1103+ assert ! ( input. openapi. is_none( ) ) ;
1104+ }
1105+
1106+ #[ test]
1107+ fn test_auto_router_input_parse_string_as_dir ( ) {
1108+ let tokens = quote:: quote!( "routes" ) ;
1109+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1110+ assert_eq ! ( input. dir. unwrap( ) . value( ) , "routes" ) ;
1111+ }
1112+
1113+ #[ test]
1114+ fn test_auto_router_input_parse_openapi_single ( ) {
1115+ let tokens = quote:: quote!( openapi = "openapi.json" ) ;
1116+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1117+ let openapi = input. openapi . unwrap ( ) ;
1118+ assert_eq ! ( openapi. len( ) , 1 ) ;
1119+ assert_eq ! ( openapi[ 0 ] . value( ) , "openapi.json" ) ;
1120+ }
1121+
1122+ #[ test]
1123+ fn test_auto_router_input_parse_openapi_array ( ) {
1124+ let tokens = quote:: quote!( openapi = [ "a.json" , "b.json" ] ) ;
1125+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1126+ let openapi = input. openapi . unwrap ( ) ;
1127+ assert_eq ! ( openapi. len( ) , 2 ) ;
1128+ }
1129+
1130+ #[ test]
1131+ fn test_auto_router_input_parse_title_version ( ) {
1132+ let tokens = quote:: quote!( title = "My API" , version = "2.0.0" ) ;
1133+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1134+ assert_eq ! ( input. title. unwrap( ) . value( ) , "My API" ) ;
1135+ assert_eq ! ( input. version. unwrap( ) . value( ) , "2.0.0" ) ;
1136+ }
1137+
1138+ #[ test]
1139+ fn test_auto_router_input_parse_docs_redoc ( ) {
1140+ let tokens = quote:: quote!( docs_url = "/docs" , redoc_url = "/redoc" ) ;
1141+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1142+ assert_eq ! ( input. docs_url. unwrap( ) . value( ) , "/docs" ) ;
1143+ assert_eq ! ( input. redoc_url. unwrap( ) . value( ) , "/redoc" ) ;
1144+ }
1145+
1146+ #[ test]
1147+ fn test_auto_router_input_parse_servers_single ( ) {
1148+ let tokens = quote:: quote!( servers = "http://localhost:3000" ) ;
1149+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1150+ let servers = input. servers . unwrap ( ) ;
1151+ assert_eq ! ( servers. len( ) , 1 ) ;
1152+ assert_eq ! ( servers[ 0 ] . url, "http://localhost:3000" ) ;
1153+ assert ! ( servers[ 0 ] . description. is_none( ) ) ;
1154+ }
1155+
1156+ #[ test]
1157+ fn test_auto_router_input_parse_servers_array_strings ( ) {
1158+ let tokens = quote:: quote!( servers = [ "http://localhost:3000" , "https://api.example.com" ] ) ;
1159+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1160+ let servers = input. servers . unwrap ( ) ;
1161+ assert_eq ! ( servers. len( ) , 2 ) ;
1162+ }
1163+
1164+ #[ test]
1165+ fn test_auto_router_input_parse_servers_tuple ( ) {
1166+ let tokens = quote:: quote!( servers = [ ( "http://localhost:3000" , "Development" ) ] ) ;
1167+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1168+ let servers = input. servers . unwrap ( ) ;
1169+ assert_eq ! ( servers. len( ) , 1 ) ;
1170+ assert_eq ! ( servers[ 0 ] . url, "http://localhost:3000" ) ;
1171+ assert_eq ! ( servers[ 0 ] . description, Some ( "Development" . to_string( ) ) ) ;
1172+ }
1173+
1174+ #[ test]
1175+ fn test_auto_router_input_parse_servers_struct ( ) {
1176+ let tokens =
1177+ quote:: quote!( servers = [ { url = "http://localhost:3000" , description = "Dev" } ] ) ;
1178+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1179+ let servers = input. servers . unwrap ( ) ;
1180+ assert_eq ! ( servers. len( ) , 1 ) ;
1181+ assert_eq ! ( servers[ 0 ] . url, "http://localhost:3000" ) ;
1182+ assert_eq ! ( servers[ 0 ] . description, Some ( "Dev" . to_string( ) ) ) ;
1183+ }
1184+
1185+ #[ test]
1186+ fn test_auto_router_input_parse_servers_single_struct ( ) {
1187+ let tokens = quote:: quote!( servers = { url = "https://api.example.com" } ) ;
1188+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1189+ let servers = input. servers . unwrap ( ) ;
1190+ assert_eq ! ( servers. len( ) , 1 ) ;
1191+ assert_eq ! ( servers[ 0 ] . url, "https://api.example.com" ) ;
1192+ }
1193+
1194+ #[ test]
1195+ fn test_auto_router_input_parse_unknown_field ( ) {
1196+ let tokens = quote:: quote!( unknown_field = "value" ) ;
1197+ let result: syn:: Result < AutoRouterInput > = syn:: parse2 ( tokens) ;
1198+ assert ! ( result. is_err( ) ) ;
1199+ }
1200+
1201+ #[ test]
1202+ fn test_auto_router_input_parse_all_fields ( ) {
1203+ let tokens = quote:: quote!(
1204+ dir = "api" ,
1205+ openapi = "openapi.json" ,
1206+ title = "Test API" ,
1207+ version = "1.0.0" ,
1208+ docs_url = "/docs" ,
1209+ redoc_url = "/redoc" ,
1210+ servers = "http://localhost:3000"
1211+ ) ;
1212+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1213+ assert ! ( input. dir. is_some( ) ) ;
1214+ assert ! ( input. openapi. is_some( ) ) ;
1215+ assert ! ( input. title. is_some( ) ) ;
1216+ assert ! ( input. version. is_some( ) ) ;
1217+ assert ! ( input. docs_url. is_some( ) ) ;
1218+ assert ! ( input. redoc_url. is_some( ) ) ;
1219+ assert ! ( input. servers. is_some( ) ) ;
1220+ }
1221+
1222+ #[ test]
1223+ fn test_generate_router_code_with_docs ( ) {
1224+ let metadata = CollectedMetadata :: new ( ) ;
1225+ let docs_info = Some ( ( "/docs" . to_string ( ) , r#"{"openapi":"3.1.0"}"# . to_string ( ) ) ) ;
1226+
1227+ let result = generate_router_code ( & metadata, docs_info, None ) ;
1228+ let code = result. to_string ( ) ;
1229+
1230+ assert ! ( code. contains( "/docs" ) ) ;
1231+ assert ! ( code. contains( "swagger-ui" ) ) ;
1232+ }
1233+
1234+ #[ test]
1235+ fn test_generate_router_code_with_redoc ( ) {
1236+ let metadata = CollectedMetadata :: new ( ) ;
1237+ let redoc_info = Some ( ( "/redoc" . to_string ( ) , r#"{"openapi":"3.1.0"}"# . to_string ( ) ) ) ;
1238+
1239+ let result = generate_router_code ( & metadata, None , redoc_info) ;
1240+ let code = result. to_string ( ) ;
1241+
1242+ assert ! ( code. contains( "/redoc" ) ) ;
1243+ assert ! ( code. contains( "redoc" ) ) ;
1244+ }
1245+
1246+ #[ test]
1247+ fn test_generate_router_code_with_both_docs ( ) {
1248+ let metadata = CollectedMetadata :: new ( ) ;
1249+ let docs_info = Some ( ( "/docs" . to_string ( ) , r#"{"openapi":"3.1.0"}"# . to_string ( ) ) ) ;
1250+ let redoc_info = Some ( ( "/redoc" . to_string ( ) , r#"{"openapi":"3.1.0"}"# . to_string ( ) ) ) ;
1251+
1252+ let result = generate_router_code ( & metadata, docs_info, redoc_info) ;
1253+ let code = result. to_string ( ) ;
1254+
1255+ assert ! ( code. contains( "/docs" ) ) ;
1256+ assert ! ( code. contains( "/redoc" ) ) ;
1257+ }
1258+
1259+ #[ test]
1260+ fn test_parse_server_struct_url_only ( ) {
1261+ // Test server struct parsing via AutoRouterInput
1262+ let tokens = quote:: quote!( servers = { url = "http://localhost:3000" } ) ;
1263+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1264+ let servers = input. servers . unwrap ( ) ;
1265+ assert_eq ! ( servers. len( ) , 1 ) ;
1266+ assert_eq ! ( servers[ 0 ] . url, "http://localhost:3000" ) ;
1267+ assert ! ( servers[ 0 ] . description. is_none( ) ) ;
1268+ }
1269+
1270+ #[ test]
1271+ fn test_parse_server_struct_with_description ( ) {
1272+ let tokens =
1273+ quote:: quote!( servers = { url = "http://localhost:3000" , description = "Local" } ) ;
1274+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1275+ let servers = input. servers . unwrap ( ) ;
1276+ assert_eq ! ( servers[ 0 ] . description, Some ( "Local" . to_string( ) ) ) ;
1277+ }
1278+
1279+ #[ test]
1280+ fn test_parse_server_struct_unknown_field ( ) {
1281+ let tokens = quote:: quote!( servers = { url = "http://localhost:3000" , unknown = "test" } ) ;
1282+ let result: syn:: Result < AutoRouterInput > = syn:: parse2 ( tokens) ;
1283+ assert ! ( result. is_err( ) ) ;
1284+ }
1285+
1286+ #[ test]
1287+ fn test_parse_server_struct_missing_url ( ) {
1288+ let tokens = quote:: quote!( servers = { description = "test" } ) ;
1289+ let result: syn:: Result < AutoRouterInput > = syn:: parse2 ( tokens) ;
1290+ assert ! ( result. is_err( ) ) ;
1291+ }
1292+
1293+ #[ test]
1294+ fn test_parse_servers_tuple_url_only ( ) {
1295+ let tokens = quote:: quote!( servers = [ ( "http://localhost:3000" ) ] ) ;
1296+ let input: AutoRouterInput = syn:: parse2 ( tokens) . unwrap ( ) ;
1297+ let servers = input. servers . unwrap ( ) ;
1298+ assert_eq ! ( servers. len( ) , 1 ) ;
1299+ assert ! ( servers[ 0 ] . description. is_none( ) ) ;
1300+ }
1301+
1302+ #[ test]
1303+ fn test_parse_servers_invalid_url ( ) {
1304+ let tokens = quote:: quote!( servers = "invalid-url" ) ;
1305+ let result: syn:: Result < AutoRouterInput > = syn:: parse2 ( tokens) ;
1306+ assert ! ( result. is_err( ) ) ;
1307+ }
1308+
1309+ #[ test]
1310+ fn test_auto_router_input_parse_invalid_token ( ) {
1311+ // Test line 149: neither ident nor string literal triggers lookahead error
1312+ let tokens = quote:: quote!( 123 ) ;
1313+ let result: syn:: Result < AutoRouterInput > = syn:: parse2 ( tokens) ;
1314+ assert ! ( result. is_err( ) ) ;
1315+ }
1316+
1317+ #[ test]
1318+ fn test_auto_router_input_empty ( ) {
1319+ // Test empty input - should use defaults/env vars
1320+ let tokens = quote:: quote!( ) ;
1321+ let result: syn:: Result < AutoRouterInput > = syn:: parse2 ( tokens) ;
1322+ assert ! ( result. is_ok( ) ) ;
1323+ }
1324+
1325+ #[ test]
1326+ fn test_auto_router_input_multiple_commas ( ) {
1327+ // Test input with trailing comma
1328+ let tokens = quote:: quote!( dir = "api" , ) ;
1329+ let result: syn:: Result < AutoRouterInput > = syn:: parse2 ( tokens) ;
1330+ assert ! ( result. is_ok( ) ) ;
1331+ }
1332+
1333+ #[ test]
1334+ fn test_auto_router_input_no_comma ( ) {
1335+ // Test input without comma between fields (should stop at second field)
1336+ let tokens = quote:: quote!( dir = "api" title = "Test" ) ;
1337+ let result: syn:: Result < AutoRouterInput > = syn:: parse2 ( tokens) ;
1338+ // This should fail or only parse first field
1339+ assert ! ( result. is_err( ) ) ;
1340+ }
10441341}
0 commit comments