@@ -1027,4 +1027,320 @@ public function testGetConditionalDisplaySettingsWhenTriggerColumnDeleted()
10271027 $ this ->assertCount (1 , $ settings );
10281028 $ this ->assertNull ($ settings [0 ]['trigger_column_type ' ]);
10291029 }
1030+
1031+ /**
1032+ * hasCyclicDependency: 循環依存がない場合はfalseを返す
1033+ *
1034+ * @test
1035+ */
1036+ public function testHasCyclicDependencyReturnsFalseWhenNoCycle ()
1037+ {
1038+ // テスト用ユーザーを作成
1039+ $ user = User::factory ()->create ();
1040+
1041+ // 項目セットを作成
1042+ $ columns_set = UsersColumnsSet::create ([
1043+ 'name ' => 'テスト項目セット ' ,
1044+ 'display_sequence ' => 1 ,
1045+ 'created_id ' => $ user ->id ,
1046+ 'updated_id ' => $ user ->id ,
1047+ ]);
1048+
1049+ // 項目A、B、Cを作成(A→B→Cの依存関係)
1050+ $ column_a = UsersColumns::create ([
1051+ 'columns_set_id ' => $ columns_set ->id ,
1052+ 'column_type ' => UserColumnType::text,
1053+ 'column_name ' => '項目A ' ,
1054+ 'required ' => Required::off,
1055+ 'display_sequence ' => 1 ,
1056+ 'created_id ' => $ user ->id ,
1057+ 'updated_id ' => $ user ->id ,
1058+ ]);
1059+
1060+ $ column_b = UsersColumns::create ([
1061+ 'columns_set_id ' => $ columns_set ->id ,
1062+ 'column_type ' => UserColumnType::text,
1063+ 'column_name ' => '項目B ' ,
1064+ 'required ' => Required::off,
1065+ 'conditional_display_flag ' => ShowType::show,
1066+ 'conditional_trigger_column_id ' => $ column_a ->id ,
1067+ 'conditional_operator ' => ConditionalOperator::equals,
1068+ 'conditional_value ' => 'test ' ,
1069+ 'display_sequence ' => 2 ,
1070+ 'created_id ' => $ user ->id ,
1071+ 'updated_id ' => $ user ->id ,
1072+ ]);
1073+
1074+ $ column_c = UsersColumns::create ([
1075+ 'columns_set_id ' => $ columns_set ->id ,
1076+ 'column_type ' => UserColumnType::text,
1077+ 'column_name ' => '項目C ' ,
1078+ 'required ' => Required::off,
1079+ 'conditional_display_flag ' => ShowType::show,
1080+ 'conditional_trigger_column_id ' => $ column_b ->id ,
1081+ 'conditional_operator ' => ConditionalOperator::equals,
1082+ 'conditional_value ' => 'test ' ,
1083+ 'display_sequence ' => 3 ,
1084+ 'created_id ' => $ user ->id ,
1085+ 'updated_id ' => $ user ->id ,
1086+ ]);
1087+
1088+ // テスト実行: Aのトリガーとして新しい項目Dを設定しても循環しない
1089+ $ has_cycle = UsersTool::hasCyclicDependency ($ column_a ->id , 999 , $ columns_set ->id );
1090+
1091+ // 検証: 循環依存なし
1092+ $ this ->assertFalse ($ has_cycle );
1093+ }
1094+
1095+ /**
1096+ * hasCyclicDependency: 直接的な循環依存を検出する(A→B→A)
1097+ *
1098+ * @test
1099+ */
1100+ public function testHasCyclicDependencyDetectsDirectCycle ()
1101+ {
1102+ // テスト用ユーザーを作成
1103+ $ user = User::factory ()->create ();
1104+
1105+ // 項目セットを作成
1106+ $ columns_set = UsersColumnsSet::create ([
1107+ 'name ' => 'テスト項目セット ' ,
1108+ 'display_sequence ' => 1 ,
1109+ 'created_id ' => $ user ->id ,
1110+ 'updated_id ' => $ user ->id ,
1111+ ]);
1112+
1113+ // 項目A、Bを作成
1114+ $ column_a = UsersColumns::create ([
1115+ 'columns_set_id ' => $ columns_set ->id ,
1116+ 'column_type ' => UserColumnType::text,
1117+ 'column_name ' => '項目A ' ,
1118+ 'required ' => Required::off,
1119+ 'display_sequence ' => 1 ,
1120+ 'created_id ' => $ user ->id ,
1121+ 'updated_id ' => $ user ->id ,
1122+ ]);
1123+
1124+ $ column_b = UsersColumns::create ([
1125+ 'columns_set_id ' => $ columns_set ->id ,
1126+ 'column_type ' => UserColumnType::text,
1127+ 'column_name ' => '項目B ' ,
1128+ 'required ' => Required::off,
1129+ 'conditional_display_flag ' => ShowType::show,
1130+ 'conditional_trigger_column_id ' => $ column_a ->id ,
1131+ 'conditional_operator ' => ConditionalOperator::equals,
1132+ 'conditional_value ' => 'test ' ,
1133+ 'display_sequence ' => 2 ,
1134+ 'created_id ' => $ user ->id ,
1135+ 'updated_id ' => $ user ->id ,
1136+ ]);
1137+
1138+ // テスト実行: AのトリガーとしてBを設定すると循環する(A→B→A)
1139+ $ has_cycle = UsersTool::hasCyclicDependency ($ column_a ->id , $ column_b ->id , $ columns_set ->id );
1140+
1141+ // 検証: 循環依存あり
1142+ $ this ->assertTrue ($ has_cycle );
1143+ }
1144+
1145+ /**
1146+ * hasCyclicDependency: 間接的な循環依存を検出する(A→B→C→A)
1147+ *
1148+ * @test
1149+ */
1150+ public function testHasCyclicDependencyDetectsIndirectCycle ()
1151+ {
1152+ // テスト用ユーザーを作成
1153+ $ user = User::factory ()->create ();
1154+
1155+ // 項目セットを作成
1156+ $ columns_set = UsersColumnsSet::create ([
1157+ 'name ' => 'テスト項目セット ' ,
1158+ 'display_sequence ' => 1 ,
1159+ 'created_id ' => $ user ->id ,
1160+ 'updated_id ' => $ user ->id ,
1161+ ]);
1162+
1163+ // 項目A、B、Cを作成(B→C、C→Aと設定)
1164+ $ column_a = UsersColumns::create ([
1165+ 'columns_set_id ' => $ columns_set ->id ,
1166+ 'column_type ' => UserColumnType::text,
1167+ 'column_name ' => '項目A ' ,
1168+ 'required ' => Required::off,
1169+ 'display_sequence ' => 1 ,
1170+ 'created_id ' => $ user ->id ,
1171+ 'updated_id ' => $ user ->id ,
1172+ ]);
1173+
1174+ $ column_b = UsersColumns::create ([
1175+ 'columns_set_id ' => $ columns_set ->id ,
1176+ 'column_type ' => UserColumnType::text,
1177+ 'column_name ' => '項目B ' ,
1178+ 'required ' => Required::off,
1179+ 'display_sequence ' => 2 ,
1180+ 'created_id ' => $ user ->id ,
1181+ 'updated_id ' => $ user ->id ,
1182+ ]);
1183+
1184+ $ column_c = UsersColumns::create ([
1185+ 'columns_set_id ' => $ columns_set ->id ,
1186+ 'column_type ' => UserColumnType::text,
1187+ 'column_name ' => '項目C ' ,
1188+ 'required ' => Required::off,
1189+ 'conditional_display_flag ' => ShowType::show,
1190+ 'conditional_trigger_column_id ' => $ column_b ->id ,
1191+ 'conditional_operator ' => ConditionalOperator::equals,
1192+ 'conditional_value ' => 'test ' ,
1193+ 'display_sequence ' => 3 ,
1194+ 'created_id ' => $ user ->id ,
1195+ 'updated_id ' => $ user ->id ,
1196+ ]);
1197+
1198+ // Cのトリガーとして、さらにAを設定
1199+ $ column_a ->update ([
1200+ 'conditional_display_flag ' => ShowType::show,
1201+ 'conditional_trigger_column_id ' => $ column_c ->id ,
1202+ 'conditional_operator ' => ConditionalOperator::equals,
1203+ 'conditional_value ' => 'test ' ,
1204+ ]);
1205+
1206+ // テスト実行: BのトリガーとしてAを設定すると循環する(B→A→C→B)
1207+ $ has_cycle = UsersTool::hasCyclicDependency ($ column_b ->id , $ column_a ->id , $ columns_set ->id );
1208+
1209+ // 検証: 循環依存あり
1210+ $ this ->assertTrue ($ has_cycle );
1211+ }
1212+
1213+ /**
1214+ * hasCyclicDependency: トリガーが未設定の場合はfalseを返す
1215+ *
1216+ * @test
1217+ */
1218+ public function testHasCyclicDependencyReturnsFalseWhenNoTrigger ()
1219+ {
1220+ // テスト用ユーザーを作成
1221+ $ user = User::factory ()->create ();
1222+
1223+ // 項目セットを作成
1224+ $ columns_set = UsersColumnsSet::create ([
1225+ 'name ' => 'テスト項目セット ' ,
1226+ 'display_sequence ' => 1 ,
1227+ 'created_id ' => $ user ->id ,
1228+ 'updated_id ' => $ user ->id ,
1229+ ]);
1230+
1231+ // 項目Aを作成
1232+ $ column_a = UsersColumns::create ([
1233+ 'columns_set_id ' => $ columns_set ->id ,
1234+ 'column_type ' => UserColumnType::text,
1235+ 'column_name ' => '項目A ' ,
1236+ 'required ' => Required::off,
1237+ 'display_sequence ' => 1 ,
1238+ 'created_id ' => $ user ->id ,
1239+ 'updated_id ' => $ user ->id ,
1240+ ]);
1241+
1242+ // テスト実行: トリガーがnullの場合
1243+ $ has_cycle = UsersTool::hasCyclicDependency ($ column_a ->id , null , $ columns_set ->id );
1244+
1245+ // 検証: 循環依存なし
1246+ $ this ->assertFalse ($ has_cycle );
1247+ }
1248+
1249+ /**
1250+ * hasCyclicDependency: 複雑な依存関係でも循環を正しく検出する
1251+ *
1252+ * @test
1253+ */
1254+ public function testHasCyclicDependencyDetectsComplexCycle ()
1255+ {
1256+ // テスト用ユーザーを作成
1257+ $ user = User::factory ()->create ();
1258+
1259+ // 項目セットを作成
1260+ $ columns_set = UsersColumnsSet::create ([
1261+ 'name ' => 'テスト項目セット ' ,
1262+ 'display_sequence ' => 1 ,
1263+ 'created_id ' => $ user ->id ,
1264+ 'updated_id ' => $ user ->id ,
1265+ ]);
1266+
1267+ // 項目A, B, C, D, Eを作成(A→B→D、C→D、D→Eの依存関係)
1268+ $ column_a = UsersColumns::create ([
1269+ 'columns_set_id ' => $ columns_set ->id ,
1270+ 'column_type ' => UserColumnType::text,
1271+ 'column_name ' => '項目A ' ,
1272+ 'required ' => Required::off,
1273+ 'display_sequence ' => 1 ,
1274+ 'created_id ' => $ user ->id ,
1275+ 'updated_id ' => $ user ->id ,
1276+ ]);
1277+
1278+ $ column_b = UsersColumns::create ([
1279+ 'columns_set_id ' => $ columns_set ->id ,
1280+ 'column_type ' => UserColumnType::text,
1281+ 'column_name ' => '項目B ' ,
1282+ 'required ' => Required::off,
1283+ 'conditional_display_flag ' => ShowType::show,
1284+ 'conditional_trigger_column_id ' => $ column_a ->id ,
1285+ 'conditional_operator ' => ConditionalOperator::equals,
1286+ 'conditional_value ' => 'test ' ,
1287+ 'display_sequence ' => 2 ,
1288+ 'created_id ' => $ user ->id ,
1289+ 'updated_id ' => $ user ->id ,
1290+ ]);
1291+
1292+ $ column_c = UsersColumns::create ([
1293+ 'columns_set_id ' => $ columns_set ->id ,
1294+ 'column_type ' => UserColumnType::text,
1295+ 'column_name ' => '項目C ' ,
1296+ 'required ' => Required::off,
1297+ 'display_sequence ' => 3 ,
1298+ 'created_id ' => $ user ->id ,
1299+ 'updated_id ' => $ user ->id ,
1300+ ]);
1301+
1302+ $ column_d = UsersColumns::create ([
1303+ 'columns_set_id ' => $ columns_set ->id ,
1304+ 'column_type ' => UserColumnType::text,
1305+ 'column_name ' => '項目D ' ,
1306+ 'required ' => Required::off,
1307+ 'conditional_display_flag ' => ShowType::show,
1308+ 'conditional_trigger_column_id ' => $ column_b ->id ,
1309+ 'conditional_operator ' => ConditionalOperator::equals,
1310+ 'conditional_value ' => 'test ' ,
1311+ 'display_sequence ' => 4 ,
1312+ 'created_id ' => $ user ->id ,
1313+ 'updated_id ' => $ user ->id ,
1314+ ]);
1315+
1316+ $ column_e = UsersColumns::create ([
1317+ 'columns_set_id ' => $ columns_set ->id ,
1318+ 'column_type ' => UserColumnType::text,
1319+ 'column_name ' => '項目E ' ,
1320+ 'required ' => Required::off,
1321+ 'conditional_display_flag ' => ShowType::show,
1322+ 'conditional_trigger_column_id ' => $ column_d ->id ,
1323+ 'conditional_operator ' => ConditionalOperator::equals,
1324+ 'conditional_value ' => 'test ' ,
1325+ 'display_sequence ' => 5 ,
1326+ 'created_id ' => $ user ->id ,
1327+ 'updated_id ' => $ user ->id ,
1328+ ]);
1329+
1330+ // Cのトリガーとして、Dを設定(C→D)
1331+ $ column_c ->update ([
1332+ 'conditional_display_flag ' => ShowType::show,
1333+ 'conditional_trigger_column_id ' => $ column_d ->id ,
1334+ 'conditional_operator ' => ConditionalOperator::equals,
1335+ 'conditional_value ' => 'test ' ,
1336+ ]);
1337+
1338+ // テスト実行1: EのトリガーとしてCを設定しても循環しない(E→C→D→B→Aで終わり)
1339+ $ has_cycle1 = UsersTool::hasCyclicDependency ($ column_e ->id , $ column_c ->id , $ columns_set ->id );
1340+ $ this ->assertFalse ($ has_cycle1 );
1341+
1342+ // テスト実行2: AのトリガーとしてEを設定すると循環する(A→E→D→B→A)
1343+ $ has_cycle2 = UsersTool::hasCyclicDependency ($ column_a ->id , $ column_e ->id , $ columns_set ->id );
1344+ $ this ->assertTrue ($ has_cycle2 );
1345+ }
10301346}
0 commit comments