Skip to content

Commit 53509f5

Browse files
committed
Update
1 parent da1b700 commit 53509f5

3 files changed

Lines changed: 38 additions & 5 deletions

File tree

MCPForUnity/Editor/Tools/Prefabs/ManagePrefabs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1170,7 +1170,7 @@ private static (int removedCount, ErrorResponse error) RemoveChildren(JToken del
11701170
string childPath = childToken.Type == JTokenType.String ? childToken.ToString() : childToken["name"]?.ToString();
11711171
if (string.IsNullOrEmpty(childPath))
11721172
{
1173-
return (removedCount, new ErrorResponse("'delete_child' must be a string or object with 'name' field."));
1173+
return (removedCount, new ErrorResponse("'deleteChild'/'delete_child' entries must be a string or object with 'name' field."));
11741174
}
11751175

11761176
// Find the child to remove

Server/src/cli/commands/prefab.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ def _parse_vector3(value: str) -> list[float]:
256256
raise click.BadParameter("Must be 'x,y,z' format")
257257
try:
258258
return [float(p.strip()) for p in parts]
259-
except ValueError:
260-
raise click.BadParameter(f"All components must be numeric, got: '{value}'")
259+
except ValueError as e:
260+
raise click.BadParameter(f"All components must be numeric, got: '{value}'") from e
261261

262262

263263
def _parse_property(prop_str: str) -> tuple[str, str, Any]:
@@ -268,7 +268,9 @@ def _parse_property(prop_str: str) -> tuple[str, str, Any]:
268268
if "." not in comp_prop:
269269
raise click.BadParameter("Must be 'Component.prop=value' format")
270270
component, prop = comp_prop.rsplit(".", 1)
271-
271+
if not component.strip() or not prop.strip():
272+
raise click.BadParameter(f"Component and property must be non-empty in '{comp_prop}', expected 'Component.prop=value'")
273+
272274
val_str = val_str.strip()
273275

274276
# Parse booleans
@@ -363,9 +365,12 @@ def modify(path: str, target: Optional[str], position: Optional[str], rotation:
363365
params["deleteChild"] = list(delete_child)
364366
if create_child:
365367
try:
366-
params["createChild"] = json.loads(create_child)
368+
parsed = json.loads(create_child)
367369
except json.JSONDecodeError as e:
368370
raise click.BadParameter(f"Invalid JSON for --create-child: {e}") from e
371+
if not isinstance(parsed, dict):
372+
raise click.BadParameter(f"--create-child must be a JSON object, got {type(parsed).__name__}")
373+
params["createChild"] = parsed
369374

370375
result = run_command("manage_prefabs", params, config)
371376
click.echo(format_output(result, config.format))

Server/tests/test_cli.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,16 @@ def test_prefab_modify_invalid_create_child_json(self, runner, mock_unity_respon
732732
"--create-child", "not valid json"
733733
])
734734
assert result.exit_code != 0
735+
assert "Invalid JSON" in result.output
736+
737+
def test_prefab_modify_create_child_non_object_json(self, runner, mock_unity_response):
738+
"""Test prefab modify rejects non-object JSON for create-child."""
739+
result = runner.invoke(cli, [
740+
"prefab", "modify", "Assets/Prefabs/Player.prefab",
741+
"--create-child", '"just a string"'
742+
])
743+
assert result.exit_code != 0
744+
assert "must be a JSON object" in result.output
735745

736746
def test_prefab_modify_active_state(self, runner, mock_unity_response):
737747
"""Test prefab modify active/inactive flag."""
@@ -805,6 +815,24 @@ def test_prefab_modify_set_property_string_value(self, runner, mock_unity_respon
805815
params = call_args[1]
806816
assert params["componentProperties"]["MyScript"]["label"] == "hello world"
807817

818+
def test_prefab_modify_set_property_empty_component(self, runner, mock_unity_response):
819+
"""Test prefab modify rejects empty component name in set-property."""
820+
result = runner.invoke(cli, [
821+
"prefab", "modify", "Assets/Prefabs/Player.prefab",
822+
"--set-property", ".mass=5"
823+
])
824+
assert result.exit_code != 0
825+
assert "non-empty" in result.output
826+
827+
def test_prefab_modify_set_property_empty_prop(self, runner, mock_unity_response):
828+
"""Test prefab modify rejects empty property name in set-property."""
829+
result = runner.invoke(cli, [
830+
"prefab", "modify", "Assets/Prefabs/Player.prefab",
831+
"--set-property", "Rigidbody.=5"
832+
])
833+
assert result.exit_code != 0
834+
assert "non-empty" in result.output
835+
808836
def test_prefab_modify_no_options_sends_minimal_params(self, runner, mock_unity_response):
809837
"""Test prefab modify with no options sends only action and prefabPath."""
810838
with patch("cli.commands.prefab.run_command", return_value=mock_unity_response) as mock_run:

0 commit comments

Comments
 (0)