@@ -1100,4 +1100,319 @@ pub const NOT_STRUCT: i32 = 1;
11001100 "Module path should contain 'special_item'"
11011101 ) ;
11021102 }
1103+
1104+ // ============================================================
1105+ // Coverage tests for find_fk_column_from_target_entity (lines 287-333)
1106+ // ============================================================
1107+
1108+ #[ test]
1109+ #[ serial]
1110+ fn test_find_fk_column_from_target_entity_success ( ) {
1111+ // Tests: Full success path - find FK column from target entity
1112+ // Covers lines 287, 291-292, 296, 298, 305, 307-309, 312, 315-317, 320-323, 325
1113+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
1114+ let src_dir = temp_dir. path ( ) . join ( "src" ) ;
1115+ let models_dir = src_dir. join ( "models" ) ;
1116+ std:: fs:: create_dir_all ( & models_dir) . unwrap ( ) ;
1117+
1118+ // Create notification.rs with a BelongsTo relation that has relation_enum matching via_rel
1119+ let notification_model = r#"
1120+ pub struct Model {
1121+ pub id: i32,
1122+ pub message: String,
1123+ pub target_user_id: i32,
1124+ #[sea_orm(belongs_to = "super::user::Entity", from = "target_user_id", to = "id", relation_enum = "TargetUser")]
1125+ pub target_user: BelongsTo<super::user::Entity>,
1126+ }
1127+ "# ;
1128+ std:: fs:: write ( models_dir. join ( "notification.rs" ) , notification_model) . unwrap ( ) ;
1129+
1130+ let original = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
1131+ unsafe { std:: env:: set_var ( "CARGO_MANIFEST_DIR" , temp_dir. path ( ) ) } ;
1132+
1133+ let result =
1134+ find_fk_column_from_target_entity ( "crate::models::notification::Schema" , "TargetUser" ) ;
1135+
1136+ unsafe {
1137+ if let Some ( dir) = original {
1138+ std:: env:: set_var ( "CARGO_MANIFEST_DIR" , dir) ;
1139+ } else {
1140+ std:: env:: remove_var ( "CARGO_MANIFEST_DIR" ) ;
1141+ }
1142+ }
1143+
1144+ assert_eq ! (
1145+ result,
1146+ Some ( "target_user_id" . to_string( ) ) ,
1147+ "Should find FK column 'target_user_id'"
1148+ ) ;
1149+ }
1150+
1151+ #[ test]
1152+ #[ serial]
1153+ fn test_find_fk_column_from_target_entity_mod_rs ( ) {
1154+ // Tests: Find FK column from mod.rs file (line 305 second path)
1155+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
1156+ let src_dir = temp_dir. path ( ) . join ( "src" ) ;
1157+ let models_dir = src_dir. join ( "models" ) . join ( "notification" ) ;
1158+ std:: fs:: create_dir_all ( & models_dir) . unwrap ( ) ;
1159+
1160+ let notification_model = r#"
1161+ pub struct Model {
1162+ pub id: i32,
1163+ pub sender_id: i32,
1164+ #[sea_orm(belongs_to = "super::super::user::Entity", from = "sender_id", to = "id", relation_enum = "Sender")]
1165+ pub sender: BelongsTo<super::super::user::Entity>,
1166+ }
1167+ "# ;
1168+ std:: fs:: write ( models_dir. join ( "mod.rs" ) , notification_model) . unwrap ( ) ;
1169+
1170+ let original = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
1171+ unsafe { std:: env:: set_var ( "CARGO_MANIFEST_DIR" , temp_dir. path ( ) ) } ;
1172+
1173+ let result =
1174+ find_fk_column_from_target_entity ( "crate::models::notification::Schema" , "Sender" ) ;
1175+
1176+ unsafe {
1177+ if let Some ( dir) = original {
1178+ std:: env:: set_var ( "CARGO_MANIFEST_DIR" , dir) ;
1179+ } else {
1180+ std:: env:: remove_var ( "CARGO_MANIFEST_DIR" ) ;
1181+ }
1182+ }
1183+
1184+ assert_eq ! (
1185+ result,
1186+ Some ( "sender_id" . to_string( ) ) ,
1187+ "Should find FK column from mod.rs"
1188+ ) ;
1189+ }
1190+
1191+ #[ test]
1192+ #[ serial]
1193+ fn test_find_fk_column_from_target_entity_empty_module_segments ( ) {
1194+ // Tests lines 300-301: Empty module segments return None
1195+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
1196+
1197+ let original = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
1198+ unsafe { std:: env:: set_var ( "CARGO_MANIFEST_DIR" , temp_dir. path ( ) ) } ;
1199+
1200+ // After filtering "crate", "Schema", segments is empty
1201+ let result = find_fk_column_from_target_entity ( "crate::Schema" , "SomeRelation" ) ;
1202+
1203+ unsafe {
1204+ if let Some ( dir) = original {
1205+ std:: env:: set_var ( "CARGO_MANIFEST_DIR" , dir) ;
1206+ } else {
1207+ std:: env:: remove_var ( "CARGO_MANIFEST_DIR" ) ;
1208+ }
1209+ }
1210+
1211+ assert ! ( result. is_none( ) , "Empty module segments should return None" ) ;
1212+ }
1213+
1214+ #[ test]
1215+ #[ serial]
1216+ fn test_find_fk_column_from_target_entity_file_not_found ( ) {
1217+ // Tests lines 307-309: File doesn't exist -> continue, then return None (line 333)
1218+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
1219+ let src_dir = temp_dir. path ( ) . join ( "src" ) ;
1220+ std:: fs:: create_dir_all ( & src_dir) . unwrap ( ) ;
1221+
1222+ let original = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
1223+ unsafe { std:: env:: set_var ( "CARGO_MANIFEST_DIR" , temp_dir. path ( ) ) } ;
1224+
1225+ // Path to non-existent file
1226+ let result =
1227+ find_fk_column_from_target_entity ( "crate::models::nonexistent::Schema" , "SomeRelation" ) ;
1228+
1229+ unsafe {
1230+ if let Some ( dir) = original {
1231+ std:: env:: set_var ( "CARGO_MANIFEST_DIR" , dir) ;
1232+ } else {
1233+ std:: env:: remove_var ( "CARGO_MANIFEST_DIR" ) ;
1234+ }
1235+ }
1236+
1237+ assert ! ( result. is_none( ) , "Non-existent file should return None" ) ;
1238+ }
1239+
1240+ #[ test]
1241+ #[ serial]
1242+ fn test_find_fk_column_from_target_entity_unparseable_file ( ) {
1243+ // Tests line 312: File can't be parsed -> returns None
1244+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
1245+ let src_dir = temp_dir. path ( ) . join ( "src" ) ;
1246+ let models_dir = src_dir. join ( "models" ) ;
1247+ std:: fs:: create_dir_all ( & models_dir) . unwrap ( ) ;
1248+
1249+ // Create unparseable file
1250+ std:: fs:: write ( models_dir. join ( "broken.rs" ) , "this is not valid rust {{{{" ) . unwrap ( ) ;
1251+
1252+ let original = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
1253+ unsafe { std:: env:: set_var ( "CARGO_MANIFEST_DIR" , temp_dir. path ( ) ) } ;
1254+
1255+ let result =
1256+ find_fk_column_from_target_entity ( "crate::models::broken::Schema" , "SomeRelation" ) ;
1257+
1258+ unsafe {
1259+ if let Some ( dir) = original {
1260+ std:: env:: set_var ( "CARGO_MANIFEST_DIR" , dir) ;
1261+ } else {
1262+ std:: env:: remove_var ( "CARGO_MANIFEST_DIR" ) ;
1263+ }
1264+ }
1265+
1266+ assert ! ( result. is_none( ) , "Unparseable file should return None" ) ;
1267+ }
1268+
1269+ #[ test]
1270+ #[ serial]
1271+ fn test_find_fk_column_from_target_entity_no_model_struct ( ) {
1272+ // Tests lines 315-317: File exists but has no Model struct
1273+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
1274+ let src_dir = temp_dir. path ( ) . join ( "src" ) ;
1275+ let models_dir = src_dir. join ( "models" ) ;
1276+ std:: fs:: create_dir_all ( & models_dir) . unwrap ( ) ;
1277+
1278+ // Create file without Model struct
1279+ let content = r#"
1280+ pub struct SomethingElse {
1281+ pub id: i32,
1282+ }
1283+ pub enum Status { Active, Inactive }
1284+ "# ;
1285+ std:: fs:: write ( models_dir. join ( "nomodel.rs" ) , content) . unwrap ( ) ;
1286+
1287+ let original = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
1288+ unsafe { std:: env:: set_var ( "CARGO_MANIFEST_DIR" , temp_dir. path ( ) ) } ;
1289+
1290+ let result =
1291+ find_fk_column_from_target_entity ( "crate::models::nomodel::Schema" , "SomeRelation" ) ;
1292+
1293+ unsafe {
1294+ if let Some ( dir) = original {
1295+ std:: env:: set_var ( "CARGO_MANIFEST_DIR" , dir) ;
1296+ } else {
1297+ std:: env:: remove_var ( "CARGO_MANIFEST_DIR" ) ;
1298+ }
1299+ }
1300+
1301+ assert ! (
1302+ result. is_none( ) ,
1303+ "File without Model struct should return None"
1304+ ) ;
1305+ }
1306+
1307+ #[ test]
1308+ #[ serial]
1309+ fn test_find_fk_column_from_target_entity_no_matching_relation_enum ( ) {
1310+ // Tests lines 320-323: Model exists but no field matches the via_rel
1311+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
1312+ let src_dir = temp_dir. path ( ) . join ( "src" ) ;
1313+ let models_dir = src_dir. join ( "models" ) ;
1314+ std:: fs:: create_dir_all ( & models_dir) . unwrap ( ) ;
1315+
1316+ // Create model with different relation_enum
1317+ let model = r#"
1318+ pub struct Model {
1319+ pub id: i32,
1320+ pub user_id: i32,
1321+ #[sea_orm(belongs_to = "super::user::Entity", from = "user_id", to = "id", relation_enum = "Author")]
1322+ pub user: BelongsTo<super::user::Entity>,
1323+ }
1324+ "# ;
1325+ std:: fs:: write ( models_dir. join ( "comment.rs" ) , model) . unwrap ( ) ;
1326+
1327+ let original = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
1328+ unsafe { std:: env:: set_var ( "CARGO_MANIFEST_DIR" , temp_dir. path ( ) ) } ;
1329+
1330+ // Search for "TargetUser" but only "Author" exists
1331+ let result =
1332+ find_fk_column_from_target_entity ( "crate::models::comment::Schema" , "TargetUser" ) ;
1333+
1334+ unsafe {
1335+ if let Some ( dir) = original {
1336+ std:: env:: set_var ( "CARGO_MANIFEST_DIR" , dir) ;
1337+ } else {
1338+ std:: env:: remove_var ( "CARGO_MANIFEST_DIR" ) ;
1339+ }
1340+ }
1341+
1342+ assert ! (
1343+ result. is_none( ) ,
1344+ "Non-matching relation_enum should return None"
1345+ ) ;
1346+ }
1347+
1348+ #[ test]
1349+ #[ serial]
1350+ fn test_find_fk_column_from_target_entity_tuple_struct ( ) {
1351+ // Tests line 320: Model is a tuple struct (not named fields) -> skip
1352+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
1353+ let src_dir = temp_dir. path ( ) . join ( "src" ) ;
1354+ let models_dir = src_dir. join ( "models" ) ;
1355+ std:: fs:: create_dir_all ( & models_dir) . unwrap ( ) ;
1356+
1357+ // Create tuple struct Model
1358+ let model = "pub struct Model(i32, String);" ;
1359+ std:: fs:: write ( models_dir. join ( "tuple.rs" ) , model) . unwrap ( ) ;
1360+
1361+ let original = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
1362+ unsafe { std:: env:: set_var ( "CARGO_MANIFEST_DIR" , temp_dir. path ( ) ) } ;
1363+
1364+ let result =
1365+ find_fk_column_from_target_entity ( "crate::models::tuple::Schema" , "SomeRelation" ) ;
1366+
1367+ unsafe {
1368+ if let Some ( dir) = original {
1369+ std:: env:: set_var ( "CARGO_MANIFEST_DIR" , dir) ;
1370+ } else {
1371+ std:: env:: remove_var ( "CARGO_MANIFEST_DIR" ) ;
1372+ }
1373+ }
1374+
1375+ assert ! ( result. is_none( ) , "Tuple struct Model should return None" ) ;
1376+ }
1377+
1378+ #[ test]
1379+ #[ serial]
1380+ fn test_find_fk_column_from_target_entity_field_no_from_attr ( ) {
1381+ // Tests line 325: Field matches relation_enum but has no `from` attribute
1382+ let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
1383+ let src_dir = temp_dir. path ( ) . join ( "src" ) ;
1384+ let models_dir = src_dir. join ( "models" ) ;
1385+ std:: fs:: create_dir_all ( & models_dir) . unwrap ( ) ;
1386+
1387+ // Create model with relation_enum but no `from` attribute
1388+ let model = r#"
1389+ pub struct Model {
1390+ pub id: i32,
1391+ pub user_id: i32,
1392+ #[sea_orm(belongs_to = "super::user::Entity", to = "id", relation_enum = "TargetUser")]
1393+ pub user: BelongsTo<super::user::Entity>,
1394+ }
1395+ "# ;
1396+ std:: fs:: write ( models_dir. join ( "nofrom.rs" ) , model) . unwrap ( ) ;
1397+
1398+ let original = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
1399+ unsafe { std:: env:: set_var ( "CARGO_MANIFEST_DIR" , temp_dir. path ( ) ) } ;
1400+
1401+ let result =
1402+ find_fk_column_from_target_entity ( "crate::models::nofrom::Schema" , "TargetUser" ) ;
1403+
1404+ unsafe {
1405+ if let Some ( dir) = original {
1406+ std:: env:: set_var ( "CARGO_MANIFEST_DIR" , dir) ;
1407+ } else {
1408+ std:: env:: remove_var ( "CARGO_MANIFEST_DIR" ) ;
1409+ }
1410+ }
1411+
1412+ // extract_belongs_to_from_field returns None when no `from` attr
1413+ assert ! (
1414+ result. is_none( ) ,
1415+ "Field without 'from' attribute should return None"
1416+ ) ;
1417+ }
11031418}
0 commit comments