@@ -722,6 +722,204 @@ public void ModifyContents_CreateChild_ReturnsErrorForInvalidInput()
722722
723723 #endregion
724724
725+ #region Component Properties Tests
726+
727+ [ Test ]
728+ public void ModifyContents_ComponentProperties_SetsSimpleProperties ( )
729+ {
730+ string prefabPath = CreatePrefabWithComponents ( "CompPropSimple" , typeof ( Rigidbody ) ) ;
731+
732+ try
733+ {
734+ var result = ToJObject ( ManagePrefabs . HandleCommand ( new JObject
735+ {
736+ [ "action" ] = "modify_contents" ,
737+ [ "prefabPath" ] = prefabPath ,
738+ [ "componentProperties" ] = new JObject
739+ {
740+ [ "Rigidbody" ] = new JObject
741+ {
742+ [ "mass" ] = 42f ,
743+ [ "useGravity" ] = false
744+ }
745+ }
746+ } ) ) ;
747+
748+ Assert . IsTrue ( result . Value < bool > ( "success" ) , $ "Expected success but got: { result } ") ;
749+ Assert . IsTrue ( result [ "data" ] . Value < bool > ( "modified" ) ) ;
750+
751+ // Verify changes persisted
752+ GameObject reloaded = AssetDatabase . LoadAssetAtPath < GameObject > ( prefabPath ) ;
753+ var rb = reloaded . GetComponent < Rigidbody > ( ) ;
754+ Assert . IsNotNull ( rb ) ;
755+ Assert . AreEqual ( 42f , rb . mass , 0.01f ) ;
756+ Assert . IsFalse ( rb . useGravity ) ;
757+ }
758+ finally
759+ {
760+ SafeDeleteAsset ( prefabPath ) ;
761+ }
762+ }
763+
764+ [ Test ]
765+ public void ModifyContents_ComponentProperties_SetsMultipleComponents ( )
766+ {
767+ string prefabPath = CreatePrefabWithComponents ( "CompPropMulti" , typeof ( Rigidbody ) , typeof ( Light ) ) ;
768+
769+ try
770+ {
771+ var result = ToJObject ( ManagePrefabs . HandleCommand ( new JObject
772+ {
773+ [ "action" ] = "modify_contents" ,
774+ [ "prefabPath" ] = prefabPath ,
775+ [ "componentProperties" ] = new JObject
776+ {
777+ [ "Rigidbody" ] = new JObject { [ "mass" ] = 10f } ,
778+ [ "Light" ] = new JObject { [ "intensity" ] = 3.5f }
779+ }
780+ } ) ) ;
781+
782+ Assert . IsTrue ( result . Value < bool > ( "success" ) , $ "Expected success but got: { result } ") ;
783+
784+ GameObject reloaded = AssetDatabase . LoadAssetAtPath < GameObject > ( prefabPath ) ;
785+ Assert . AreEqual ( 10f , reloaded . GetComponent < Rigidbody > ( ) . mass , 0.01f ) ;
786+ Assert . AreEqual ( 3.5f , reloaded . GetComponent < Light > ( ) . intensity , 0.01f ) ;
787+ }
788+ finally
789+ {
790+ SafeDeleteAsset ( prefabPath ) ;
791+ }
792+ }
793+
794+ [ Test ]
795+ public void ModifyContents_ComponentProperties_SetsOnChildTarget ( )
796+ {
797+ // Create a prefab with a child that has a Rigidbody
798+ EnsureFolder ( TempDirectory ) ;
799+ GameObject root = new GameObject ( "ChildTargetTest" ) ;
800+ GameObject child = new GameObject ( "Child1" ) { transform = { parent = root . transform } } ;
801+ child . AddComponent < Rigidbody > ( ) ;
802+
803+ string prefabPath = Path . Combine ( TempDirectory , "ChildTargetTest.prefab" ) . Replace ( '\\ ' , '/' ) ;
804+ PrefabUtility . SaveAsPrefabAsset ( root , prefabPath , out bool success ) ;
805+ UnityEngine . Object . DestroyImmediate ( root ) ;
806+ AssetDatabase . Refresh ( ) ;
807+ Assert . IsTrue ( success ) ;
808+
809+ try
810+ {
811+ var result = ToJObject ( ManagePrefabs . HandleCommand ( new JObject
812+ {
813+ [ "action" ] = "modify_contents" ,
814+ [ "prefabPath" ] = prefabPath ,
815+ [ "target" ] = "Child1" ,
816+ [ "componentProperties" ] = new JObject
817+ {
818+ [ "Rigidbody" ] = new JObject { [ "mass" ] = 99f , [ "drag" ] = 2.5f }
819+ }
820+ } ) ) ;
821+
822+ Assert . IsTrue ( result . Value < bool > ( "success" ) , $ "Expected success but got: { result } ") ;
823+
824+ GameObject reloaded = AssetDatabase . LoadAssetAtPath < GameObject > ( prefabPath ) ;
825+ var childRb = reloaded . transform . Find ( "Child1" ) . GetComponent < Rigidbody > ( ) ;
826+ Assert . AreEqual ( 99f , childRb . mass , 0.01f ) ;
827+ Assert . AreEqual ( 2.5f , childRb . drag , 0.01f ) ;
828+ }
829+ finally
830+ {
831+ SafeDeleteAsset ( prefabPath ) ;
832+ }
833+ }
834+
835+ [ Test ]
836+ public void ModifyContents_ComponentProperties_ReturnsErrorForMissingComponent ( )
837+ {
838+ string prefabPath = CreateTestPrefab ( "CompPropMissing" ) ;
839+
840+ try
841+ {
842+ var result = ToJObject ( ManagePrefabs . HandleCommand ( new JObject
843+ {
844+ [ "action" ] = "modify_contents" ,
845+ [ "prefabPath" ] = prefabPath ,
846+ [ "componentProperties" ] = new JObject
847+ {
848+ [ "Rigidbody" ] = new JObject { [ "mass" ] = 5f }
849+ }
850+ } ) ) ;
851+
852+ Assert . IsFalse ( result . Value < bool > ( "success" ) ) ;
853+ Assert . IsTrue ( result . Value < string > ( "error" ) . Contains ( "not found" ) ,
854+ $ "Expected 'not found' error but got: { result . Value < string > ( "error" ) } ") ;
855+ }
856+ finally
857+ {
858+ SafeDeleteAsset ( prefabPath ) ;
859+ }
860+ }
861+
862+ [ Test ]
863+ public void ModifyContents_ComponentProperties_ReturnsErrorForInvalidType ( )
864+ {
865+ string prefabPath = CreateTestPrefab ( "CompPropInvalidType" ) ;
866+
867+ try
868+ {
869+ var result = ToJObject ( ManagePrefabs . HandleCommand ( new JObject
870+ {
871+ [ "action" ] = "modify_contents" ,
872+ [ "prefabPath" ] = prefabPath ,
873+ [ "componentProperties" ] = new JObject
874+ {
875+ [ "NonexistentComponent" ] = new JObject { [ "foo" ] = "bar" }
876+ }
877+ } ) ) ;
878+
879+ Assert . IsFalse ( result . Value < bool > ( "success" ) ) ;
880+ Assert . IsTrue ( result . Value < string > ( "error" ) . Contains ( "not found" ) ,
881+ $ "Expected 'not found' error but got: { result . Value < string > ( "error" ) } ") ;
882+ }
883+ finally
884+ {
885+ SafeDeleteAsset ( prefabPath ) ;
886+ }
887+ }
888+
889+ [ Test ]
890+ public void ModifyContents_ComponentProperties_CombinesWithOtherModifications ( )
891+ {
892+ string prefabPath = CreatePrefabWithComponents ( "CompPropCombined" , typeof ( Rigidbody ) ) ;
893+
894+ try
895+ {
896+ var result = ToJObject ( ManagePrefabs . HandleCommand ( new JObject
897+ {
898+ [ "action" ] = "modify_contents" ,
899+ [ "prefabPath" ] = prefabPath ,
900+ [ "position" ] = new JArray ( 5f , 10f , 15f ) ,
901+ [ "name" ] = "RenamedWithProps" ,
902+ [ "componentProperties" ] = new JObject
903+ {
904+ [ "Rigidbody" ] = new JObject { [ "mass" ] = 25f }
905+ }
906+ } ) ) ;
907+
908+ Assert . IsTrue ( result . Value < bool > ( "success" ) , $ "Expected success but got: { result } ") ;
909+
910+ GameObject reloaded = AssetDatabase . LoadAssetAtPath < GameObject > ( prefabPath ) ;
911+ Assert . AreEqual ( "RenamedWithProps" , reloaded . name ) ;
912+ Assert . AreEqual ( new Vector3 ( 5f , 10f , 15f ) , reloaded . transform . localPosition ) ;
913+ Assert . AreEqual ( 25f , reloaded . GetComponent < Rigidbody > ( ) . mass , 0.01f ) ;
914+ }
915+ finally
916+ {
917+ SafeDeleteAsset ( prefabPath ) ;
918+ }
919+ }
920+
921+ #endregion
922+
725923 #region Error Handling
726924
727925 [ Test ]
@@ -824,6 +1022,24 @@ private static string CreateNestedTestPrefab(string name)
8241022 return path ;
8251023 }
8261024
1025+ private static string CreatePrefabWithComponents ( string name , params Type [ ] componentTypes )
1026+ {
1027+ EnsureFolder ( TempDirectory ) ;
1028+ GameObject temp = new GameObject ( name ) ;
1029+ foreach ( var t in componentTypes )
1030+ {
1031+ temp . AddComponent ( t ) ;
1032+ }
1033+
1034+ string path = Path . Combine ( TempDirectory , name + ".prefab" ) . Replace ( '\\ ' , '/' ) ;
1035+ PrefabUtility . SaveAsPrefabAsset ( temp , path , out bool success ) ;
1036+ UnityEngine . Object . DestroyImmediate ( temp ) ;
1037+ AssetDatabase . Refresh ( ) ;
1038+
1039+ if ( ! success ) throw new Exception ( $ "Failed to create test prefab at { path } ") ;
1040+ return path ;
1041+ }
1042+
8271043 private static string CreateComplexTestPrefab ( string name )
8281044 {
8291045 // Creates: Vehicle (root with BoxCollider)
0 commit comments