@mflrevan/ucp 0.3.3 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +3 -3
  2. package/package.json +8 -2
  3. package/bridge/com.ucp.bridge/CHANGELOG.md +0 -112
  4. package/bridge/com.ucp.bridge/CHANGELOG.md.meta +0 -7
  5. package/bridge/com.ucp.bridge/Editor/Bridge/BridgeServer.cs +0 -576
  6. package/bridge/com.ucp.bridge/Editor/Bridge/BridgeServer.cs.meta +0 -2
  7. package/bridge/com.ucp.bridge/Editor/Bridge.meta +0 -8
  8. package/bridge/com.ucp.bridge/Editor/Controllers/AssetController.cs +0 -530
  9. package/bridge/com.ucp.bridge/Editor/Controllers/AssetController.cs.meta +0 -2
  10. package/bridge/com.ucp.bridge/Editor/Controllers/BuildController.cs +0 -230
  11. package/bridge/com.ucp.bridge/Editor/Controllers/BuildController.cs.meta +0 -2
  12. package/bridge/com.ucp.bridge/Editor/Controllers/CompilationController.cs +0 -26
  13. package/bridge/com.ucp.bridge/Editor/Controllers/CompilationController.cs.meta +0 -2
  14. package/bridge/com.ucp.bridge/Editor/Controllers/EditorController.cs +0 -18
  15. package/bridge/com.ucp.bridge/Editor/Controllers/EditorController.cs.meta +0 -2
  16. package/bridge/com.ucp.bridge/Editor/Controllers/EditorSettingsController.cs +0 -438
  17. package/bridge/com.ucp.bridge/Editor/Controllers/EditorSettingsController.cs.meta +0 -2
  18. package/bridge/com.ucp.bridge/Editor/Controllers/FileController.cs +0 -130
  19. package/bridge/com.ucp.bridge/Editor/Controllers/FileController.cs.meta +0 -2
  20. package/bridge/com.ucp.bridge/Editor/Controllers/HierarchyController.cs +0 -319
  21. package/bridge/com.ucp.bridge/Editor/Controllers/HierarchyController.cs.meta +0 -2
  22. package/bridge/com.ucp.bridge/Editor/Controllers/LogsController.cs +0 -288
  23. package/bridge/com.ucp.bridge/Editor/Controllers/LogsController.cs.meta +0 -2
  24. package/bridge/com.ucp.bridge/Editor/Controllers/MaterialController.cs +0 -295
  25. package/bridge/com.ucp.bridge/Editor/Controllers/MaterialController.cs.meta +0 -2
  26. package/bridge/com.ucp.bridge/Editor/Controllers/ObjectReferenceResolver.cs +0 -93
  27. package/bridge/com.ucp.bridge/Editor/Controllers/ObjectReferenceResolver.cs.meta +0 -2
  28. package/bridge/com.ucp.bridge/Editor/Controllers/PlayModeController.cs +0 -84
  29. package/bridge/com.ucp.bridge/Editor/Controllers/PlayModeController.cs.meta +0 -2
  30. package/bridge/com.ucp.bridge/Editor/Controllers/PrefabController.cs +0 -242
  31. package/bridge/com.ucp.bridge/Editor/Controllers/PrefabController.cs.meta +0 -2
  32. package/bridge/com.ucp.bridge/Editor/Controllers/PropertyController.cs +0 -533
  33. package/bridge/com.ucp.bridge/Editor/Controllers/PropertyController.cs.meta +0 -2
  34. package/bridge/com.ucp.bridge/Editor/Controllers/SceneController.cs +0 -111
  35. package/bridge/com.ucp.bridge/Editor/Controllers/SceneController.cs.meta +0 -2
  36. package/bridge/com.ucp.bridge/Editor/Controllers/ScreenshotController.cs +0 -125
  37. package/bridge/com.ucp.bridge/Editor/Controllers/ScreenshotController.cs.meta +0 -2
  38. package/bridge/com.ucp.bridge/Editor/Controllers/ScriptController.cs +0 -104
  39. package/bridge/com.ucp.bridge/Editor/Controllers/ScriptController.cs.meta +0 -2
  40. package/bridge/com.ucp.bridge/Editor/Controllers/SnapshotController.cs +0 -227
  41. package/bridge/com.ucp.bridge/Editor/Controllers/SnapshotController.cs.meta +0 -2
  42. package/bridge/com.ucp.bridge/Editor/Controllers/TestRunnerController.cs +0 -240
  43. package/bridge/com.ucp.bridge/Editor/Controllers/TestRunnerController.cs.meta +0 -2
  44. package/bridge/com.ucp.bridge/Editor/Controllers/VcsController.cs +0 -611
  45. package/bridge/com.ucp.bridge/Editor/Controllers/VcsController.cs.meta +0 -2
  46. package/bridge/com.ucp.bridge/Editor/Controllers.meta +0 -8
  47. package/bridge/com.ucp.bridge/Editor/Protocol/CommandRouter.cs +0 -53
  48. package/bridge/com.ucp.bridge/Editor/Protocol/CommandRouter.cs.meta +0 -2
  49. package/bridge/com.ucp.bridge/Editor/Protocol/MessageTypes.cs +0 -80
  50. package/bridge/com.ucp.bridge/Editor/Protocol/MessageTypes.cs.meta +0 -2
  51. package/bridge/com.ucp.bridge/Editor/Protocol/MiniJson.cs +0 -358
  52. package/bridge/com.ucp.bridge/Editor/Protocol/MiniJson.cs.meta +0 -2
  53. package/bridge/com.ucp.bridge/Editor/Protocol.meta +0 -8
  54. package/bridge/com.ucp.bridge/Editor/Scripts/IUCPScript.cs +0 -37
  55. package/bridge/com.ucp.bridge/Editor/Scripts/IUCPScript.cs.meta +0 -2
  56. package/bridge/com.ucp.bridge/Editor/Scripts.meta +0 -8
  57. package/bridge/com.ucp.bridge/Editor/UCP.Bridge.Editor.asmdef +0 -16
  58. package/bridge/com.ucp.bridge/Editor/UCP.Bridge.Editor.asmdef.meta +0 -7
  59. package/bridge/com.ucp.bridge/Editor.meta +0 -8
  60. package/bridge/com.ucp.bridge/Runtime/UCP.Bridge.Runtime.asmdef +0 -14
  61. package/bridge/com.ucp.bridge/Runtime/UCP.Bridge.Runtime.asmdef.meta +0 -7
  62. package/bridge/com.ucp.bridge/Runtime.meta +0 -8
  63. package/bridge/com.ucp.bridge/Tests/Editor/ControllerSmokeTests.cs +0 -591
  64. package/bridge/com.ucp.bridge/Tests/Editor/ControllerSmokeTests.cs.meta +0 -2
  65. package/bridge/com.ucp.bridge/Tests/Editor/UCP.Bridge.Editor.Tests.asmdef +0 -12
  66. package/bridge/com.ucp.bridge/Tests/Editor/UCP.Bridge.Editor.Tests.asmdef.meta +0 -7
  67. package/bridge/com.ucp.bridge/Tests/Editor.meta +0 -8
  68. package/bridge/com.ucp.bridge/Tests.meta +0 -8
  69. package/bridge/com.ucp.bridge/package.json +0 -27
  70. package/bridge/com.ucp.bridge/package.json.meta +0 -7
@@ -1,591 +0,0 @@
1
- using System;
2
- using System.Collections;
3
- using System.Collections.Generic;
4
- using System.Text.RegularExpressions;
5
- using NUnit.Framework;
6
- using UnityEditor;
7
- using UnityEditor.SceneManagement;
8
- using UnityEngine;
9
- using UnityEngine.TestTools;
10
-
11
- namespace UCP.Bridge.Tests
12
- {
13
- public class ControllerSmokeTests
14
- {
15
- private const string TempAssetPath = "Assets/UcpControllerSmoke.asset";
16
- private const string TempReferenceAssetPath = "Assets/UcpControllerReference.asset";
17
- private const string TempPrefabPath = "Assets/UcpControllerSmoke.prefab";
18
- private const string TempMaterialPath = "Assets/UcpControllerSmoke.mat";
19
- private const string TempTextPath = "Assets/UcpControllerSmoke.txt";
20
-
21
- private CommandRouter _router;
22
-
23
- [SetUp]
24
- public void SetUp()
25
- {
26
- _router = new CommandRouter();
27
- SnapshotController.Register(_router);
28
- AssetController.Register(_router);
29
- LogsController.Register(_router);
30
- HierarchyController.Register(_router);
31
- PropertyController.Register(_router);
32
- FileController.Register(_router);
33
- MaterialController.Register(_router);
34
- PrefabController.Register(_router);
35
- BuildController.Register(_router);
36
- EditorSettingsController.Register(_router);
37
- EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
38
- DeleteTempAsset();
39
- DeleteTempReferenceAsset();
40
- DeleteTempPrefab();
41
- DeleteTempMaterial();
42
- DeleteTempTextFile();
43
- LogsController.ClearHistoryForTests();
44
- }
45
-
46
- [TearDown]
47
- public void TearDown()
48
- {
49
- DeleteTempAsset();
50
- DeleteTempReferenceAsset();
51
- DeleteTempPrefab();
52
- DeleteTempMaterial();
53
- DeleteTempTextFile();
54
- LogsController.ClearHistoryForTests();
55
- EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
56
- }
57
-
58
- [Test]
59
- public void Snapshot_DefaultDepth_ReturnsLeanRootMetadata()
60
- {
61
- var root = new GameObject("Root");
62
- var child = new GameObject("Child");
63
- child.transform.SetParent(root.transform, false);
64
-
65
- var response = _router.Dispatch("snapshot", 1, "{\"depth\":0}");
66
-
67
- Assert.That(response.error, Is.Null);
68
-
69
- var result = (Dictionary<string, object>)response.result;
70
- var objects = (List<object>)result["objects"];
71
- Assert.That(objects.Count, Is.EqualTo(1));
72
-
73
- var entry = (Dictionary<string, object>)objects[0];
74
- Assert.That(entry["name"], Is.EqualTo("Root"));
75
- Assert.That(Convert.ToInt32(entry["depth"]), Is.EqualTo(0));
76
- Assert.That(Convert.ToInt32(entry["childCount"]), Is.EqualTo(1));
77
- Assert.That(entry.ContainsKey("components"), Is.True);
78
- Assert.That(entry.ContainsKey("layerName"), Is.True);
79
- Assert.That(entry.ContainsKey("children"), Is.False);
80
- Assert.That(entry.ContainsKey("position"), Is.False);
81
- Assert.That(entry.ContainsKey("rotation"), Is.False);
82
- Assert.That(result.ContainsKey("logs"), Is.False);
83
- }
84
-
85
- [Test]
86
- public void AssetSearch_FiltersActualSubassetTypeMatches()
87
- {
88
- var root = ScriptableObject.CreateInstance<SearchRootAsset>();
89
- root.name = "SmokeRoot";
90
- AssetDatabase.CreateAsset(root, TempAssetPath);
91
-
92
- var nested = ScriptableObject.CreateInstance<SearchNestedAsset>();
93
- nested.name = "SmokeNested";
94
- AssetDatabase.AddObjectToAsset(nested, root);
95
- AssetDatabase.ImportAsset(TempAssetPath, ImportAssetOptions.ForceSynchronousImport);
96
- AssetDatabase.SaveAssets();
97
-
98
- var response = _router.Dispatch(
99
- "asset/search",
100
- 1,
101
- "{\"name\":\"SmokeNested\",\"path\":\"Assets\",\"maxResults\":10}"
102
- );
103
-
104
- Assert.That(response.error, Is.Null);
105
-
106
- var result = (Dictionary<string, object>)response.result;
107
- Assert.That(Convert.ToInt32(result["total"]), Is.GreaterThanOrEqualTo(1));
108
- Assert.That(Convert.ToInt32(result["returned"]), Is.GreaterThanOrEqualTo(1));
109
-
110
- var matches = (List<object>)result["results"];
111
- var match = FindAssetMatch(matches, TempAssetPath, "SmokeNested");
112
- Assert.That(match, Is.Not.Null);
113
- Assert.That(match["path"], Is.EqualTo(TempAssetPath));
114
- Assert.That(match["type"], Is.EqualTo("SearchNestedAsset"));
115
- Assert.That(match["name"], Is.EqualTo("SmokeNested"));
116
- Assert.That(Convert.ToBoolean(match["isSubAsset"]), Is.True);
117
- }
118
-
119
- [Test]
120
- public void LogsTail_ReturnsRequestedBufferedCount()
121
- {
122
- for (var index = 0; index < 12; index++)
123
- LogsController.RecordTestLog("info", $"log {index}");
124
-
125
- var response = _router.Dispatch("logs/tail", 1, "{\"count\":50}");
126
-
127
- Assert.That(response.error, Is.Null);
128
-
129
- var result = (Dictionary<string, object>)response.result;
130
- Assert.That(Convert.ToInt32(result["total"]), Is.EqualTo(12));
131
- Assert.That(Convert.ToInt32(result["returned"]), Is.EqualTo(12));
132
- Assert.That(Convert.ToBoolean(result["truncated"]), Is.False);
133
-
134
- var logs = (List<object>)result["logs"];
135
- var first = (Dictionary<string, object>)logs[0];
136
- Assert.That(Convert.ToInt64(first["id"]), Is.EqualTo(12));
137
- Assert.That(first.ContainsKey("messagePreview"), Is.True);
138
- }
139
-
140
- [Test]
141
- public void LogsSearch_FiltersBeforeApplyingCount()
142
- {
143
- LogsController.RecordTestLog("warning", "Target failed once");
144
- for (var index = 0; index < 8; index++)
145
- LogsController.RecordTestLog("info", $"Noise {index}");
146
-
147
- var response = _router.Dispatch("logs/search", 1, "{\"pattern\":\"Target\",\"count\":1}");
148
-
149
- Assert.That(response.error, Is.Null);
150
-
151
- var result = (Dictionary<string, object>)response.result;
152
- Assert.That(Convert.ToInt32(result["total"]), Is.EqualTo(1));
153
- Assert.That(Convert.ToInt32(result["returned"]), Is.EqualTo(1));
154
- Assert.That(Convert.ToBoolean(result["truncated"]), Is.False);
155
- }
156
-
157
- [Test]
158
- public void LogsSearch_UsesRegexAgainstBufferedHistory()
159
- {
160
- LogsController.RecordTestLog("info", "Alpha ready");
161
- LogsController.RecordTestLog("warning", "Beta failed");
162
- LogsController.RecordTestLog("error", "Gamma failed hard");
163
-
164
- var response = _router.Dispatch("logs/search", 1, "{\"pattern\":\"failed\",\"count\":20}");
165
-
166
- Assert.That(response.error, Is.Null);
167
-
168
- var result = (Dictionary<string, object>)response.result;
169
- Assert.That(Convert.ToInt32(result["total"]), Is.EqualTo(2));
170
-
171
- var logs = (List<object>)result["logs"];
172
- Assert.That(logs.Count, Is.EqualTo(2));
173
- var first = (Dictionary<string, object>)logs[0];
174
- Assert.That(first["level"], Is.EqualTo("error"));
175
- }
176
-
177
- [Test]
178
- public void LogsTail_RespectsLevelThresholdAndIdWindow()
179
- {
180
- var first = LogsController.RecordTestLog("info", "Alpha");
181
- var second = LogsController.RecordTestLog("warning", "Beta warning");
182
- var third = LogsController.RecordTestLog("error", "Gamma error");
183
-
184
- var response = _router.Dispatch(
185
- "logs/tail",
186
- 1,
187
- "{\"level\":\"warn\",\"afterId\":" + Convert.ToInt64(first["id"]) + ",\"beforeId\":" + Convert.ToInt64(third["id"]) + ",\"count\":20}"
188
- );
189
-
190
- Assert.That(response.error, Is.Null);
191
-
192
- var result = (Dictionary<string, object>)response.result;
193
- Assert.That(Convert.ToInt32(result["total"]), Is.EqualTo(1));
194
-
195
- var logs = (List<object>)result["logs"];
196
- Assert.That(logs.Count, Is.EqualTo(1));
197
- var only = (Dictionary<string, object>)logs[0];
198
- Assert.That(only["level"], Is.EqualTo("warning"));
199
- Assert.That(Convert.ToInt64(only["id"]), Is.EqualTo(Convert.ToInt64(second["id"])));
200
- }
201
-
202
- [Test]
203
- public void LogsGet_ReturnsFullMessageAndStackTrace()
204
- {
205
- var created = LogsController.RecordTestLog("error", "Exploded", "stack line 1\nstack line 2");
206
- var id = Convert.ToInt64(created["id"]);
207
-
208
- var response = _router.Dispatch("logs/get", 1, "{\"id\":" + id + "}");
209
-
210
- Assert.That(response.error, Is.Null);
211
-
212
- var result = (Dictionary<string, object>)response.result;
213
- Assert.That(result["message"], Is.EqualTo("Exploded"));
214
- Assert.That(result["stackTrace"], Is.EqualTo("stack line 1\nstack line 2"));
215
- }
216
-
217
- [Test]
218
- public void ObjectLifecycle_CreateMutateAndDelete_WorksEndToEnd()
219
- {
220
- var create = _router.Dispatch("object/create", 1, "{\"name\":\"SmokeObject\"}");
221
- Assert.That(create.error, Is.Null);
222
-
223
- var createResult = (Dictionary<string, object>)create.result;
224
- var instanceId = Convert.ToInt32(createResult["instanceId"]);
225
-
226
- var rename = _router.Dispatch("object/set-name", 1, "{\"instanceId\":" + instanceId + ",\"name\":\"RenamedSmoke\"}");
227
- Assert.That(rename.error, Is.Null);
228
-
229
- var deactivate = _router.Dispatch("object/set-active", 1, "{\"instanceId\":" + instanceId + ",\"active\":false}");
230
- Assert.That(deactivate.error, Is.Null);
231
- var deactivateResult = (Dictionary<string, object>)deactivate.result;
232
- Assert.That(Convert.ToBoolean(deactivateResult["active"]), Is.False);
233
-
234
- var activate = _router.Dispatch("object/set-active", 1, "{\"instanceId\":" + instanceId + ",\"active\":true}");
235
- Assert.That(activate.error, Is.Null);
236
-
237
- var addComponent = _router.Dispatch("object/add-component", 1, "{\"instanceId\":" + instanceId + ",\"type\":\"BoxCollider\"}");
238
- Assert.That(addComponent.error, Is.Null);
239
-
240
- var setPosition = _router.Dispatch(
241
- "object/set-property",
242
- 1,
243
- "{\"instanceId\":" + instanceId + ",\"component\":\"Transform\",\"property\":\"m_LocalPosition\",\"value\":[1,2,3]}"
244
- );
245
- Assert.That(setPosition.error, Is.Null);
246
-
247
- var getPosition = _router.Dispatch(
248
- "object/get-property",
249
- 1,
250
- "{\"instanceId\":" + instanceId + ",\"component\":\"Transform\",\"property\":\"m_LocalPosition\"}"
251
- );
252
- Assert.That(getPosition.error, Is.Null);
253
-
254
- var updated = EditorUtility.InstanceIDToObject(instanceId) as GameObject;
255
- Assert.That(updated, Is.Not.Null);
256
- var localPosition = updated.transform.localPosition;
257
- Assert.That(localPosition.x, Is.EqualTo(1f).Within(0.001f));
258
- Assert.That(localPosition.y, Is.EqualTo(2f).Within(0.001f));
259
- Assert.That(localPosition.z, Is.EqualTo(3f).Within(0.001f));
260
-
261
- var removeComponent = _router.Dispatch("object/remove-component", 1, "{\"instanceId\":" + instanceId + ",\"type\":\"BoxCollider\"}");
262
- Assert.That(removeComponent.error, Is.Null);
263
-
264
- var delete = _router.Dispatch("object/delete", 1, "{\"instanceId\":" + instanceId + "}");
265
- Assert.That(delete.error, Is.Null);
266
- Assert.That(EditorUtility.InstanceIDToObject(instanceId), Is.Null);
267
- }
268
-
269
- [Test]
270
- public void ObjectSetProperty_AssignsObjectReferenceByAssetPath()
271
- {
272
- var referencedAsset = ScriptableObject.CreateInstance<SearchRootAsset>();
273
- referencedAsset.name = "ReferenceAsset";
274
- AssetDatabase.CreateAsset(referencedAsset, TempReferenceAssetPath);
275
- AssetDatabase.SaveAssets();
276
-
277
- var go = new GameObject("ReferenceCarrier");
278
- var component = go.AddComponent<ReferenceComponent>();
279
-
280
- var response = _router.Dispatch(
281
- "object/set-property",
282
- 1,
283
- "{\"instanceId\":" + go.GetInstanceID() + ",\"component\":\"ReferenceComponent\",\"property\":\"referenceAsset\",\"value\":{\"path\":\"" + TempReferenceAssetPath + "\"}}"
284
- );
285
-
286
- Assert.That(response.error, Is.Null);
287
- Assert.That(component.referenceAsset, Is.Not.Null);
288
- Assert.That(AssetDatabase.GetAssetPath(component.referenceAsset), Is.EqualTo(TempReferenceAssetPath));
289
- }
290
-
291
- [Test]
292
- public void ObjectSetProperty_RejectsUnknownObjectReference()
293
- {
294
- var go = new GameObject("ReferenceCarrier");
295
- go.AddComponent<ReferenceComponent>();
296
-
297
- var response = _router.Dispatch(
298
- "object/set-property",
299
- 1,
300
- "{\"instanceId\":" + go.GetInstanceID() + ",\"component\":\"ReferenceComponent\",\"property\":\"referenceAsset\",\"value\":{\"path\":\"Assets/Missing.asset\"}}"
301
- );
302
-
303
- Assert.That(response.error, Is.Not.Null);
304
- Assert.That(response.error.code, Is.EqualTo(ErrorCodes.InvalidParams));
305
- }
306
-
307
- [Test]
308
- public void AssetWriteBatch_UpdatesMultipleFieldsIncludingObjectReference()
309
- {
310
- var reference = ScriptableObject.CreateInstance<SearchRootAsset>();
311
- reference.name = "ReferenceAsset";
312
- AssetDatabase.CreateAsset(reference, TempReferenceAssetPath);
313
-
314
- var asset = ScriptableObject.CreateInstance<BatchWritableAsset>();
315
- asset.maxPlayers = 2;
316
- asset.spawnDelay = 5f;
317
- AssetDatabase.CreateAsset(asset, TempAssetPath);
318
- AssetDatabase.SaveAssets();
319
-
320
- var response = _router.Dispatch(
321
- "asset/write-batch",
322
- 1,
323
- "{\"path\":\"" + TempAssetPath + "\",\"values\":{\"maxPlayers\":8,\"spawnDelay\":1.5,\"referenceAsset\":{\"path\":\"" + TempReferenceAssetPath + "\"}}}"
324
- );
325
-
326
- Assert.That(response.error, Is.Null);
327
-
328
- var reloaded = AssetDatabase.LoadAssetAtPath<BatchWritableAsset>(TempAssetPath);
329
- Assert.That(reloaded.maxPlayers, Is.EqualTo(8));
330
- Assert.That(reloaded.spawnDelay, Is.EqualTo(1.5f).Within(0.001f));
331
- Assert.That(AssetDatabase.GetAssetPath(reloaded.referenceAsset), Is.EqualTo(TempReferenceAssetPath));
332
- }
333
-
334
- [Test]
335
- public void FileController_WritePatchRead_AndRejectsPathTraversal()
336
- {
337
- var write = _router.Dispatch("file/write", 1, "{\"path\":\"Assets/UcpControllerSmoke.txt\",\"content\":\"hello smoke\"}");
338
- Assert.That(write.error, Is.Null);
339
-
340
- var patch = _router.Dispatch(
341
- "file/patch",
342
- 1,
343
- "{\"path\":\"Assets/UcpControllerSmoke.txt\",\"patch\":{\"find\":\"smoke\",\"replace\":\"patched\"}}"
344
- );
345
- Assert.That(patch.error, Is.Null);
346
-
347
- var read = _router.Dispatch("file/read", 1, "{\"path\":\"Assets/UcpControllerSmoke.txt\"}");
348
- Assert.That(read.error, Is.Null);
349
- var readResult = (Dictionary<string, object>)read.result;
350
- Assert.That(readResult["content"].ToString(), Is.EqualTo("hello patched"));
351
-
352
- var traversal = _router.Dispatch("file/read", 1, "{\"path\":\"../outside.txt\"}");
353
- Assert.That(traversal.error, Is.Not.Null);
354
- Assert.That(traversal.error.code, Is.EqualTo(ErrorCodes.FileAccessDenied));
355
- }
356
-
357
- [Test]
358
- public void MaterialController_SetAndGetFloatProperty_RoundTrips()
359
- {
360
- var shader = Shader.Find("Standard") ?? Shader.Find("Universal Render Pipeline/Lit");
361
- Assert.That(shader, Is.Not.Null);
362
-
363
- var propertyName = FindFirstFloatOrRangeProperty(shader);
364
- Assert.That(propertyName, Is.Not.Null.And.Not.Empty);
365
-
366
- var material = new Material(shader) { name = "UcpControllerSmokeMat" };
367
- AssetDatabase.CreateAsset(material, TempMaterialPath);
368
- AssetDatabase.SaveAssets();
369
-
370
- var set = _router.Dispatch(
371
- "material/set-property",
372
- 1,
373
- "{\"path\":\"Assets/UcpControllerSmoke.mat\",\"property\":\"" + propertyName + "\",\"value\":0.42}"
374
- );
375
- Assert.That(set.error, Is.Null);
376
-
377
- var get = _router.Dispatch(
378
- "material/get-property",
379
- 1,
380
- "{\"path\":\"Assets/UcpControllerSmoke.mat\",\"property\":\"" + propertyName + "\"}"
381
- );
382
- Assert.That(get.error, Is.Null);
383
-
384
- var getResult = (Dictionary<string, object>)get.result;
385
- var value = Convert.ToSingle(getResult["value"]);
386
- Assert.That(value, Is.EqualTo(0.42f).Within(0.001f));
387
- }
388
-
389
- [Test]
390
- public void PrefabController_CreateStatusOverridesAndUnpack_Works()
391
- {
392
- var create = _router.Dispatch("object/create", 1, "{\"name\":\"PrefabSource\"}");
393
- Assert.That(create.error, Is.Null);
394
- var sourceId = Convert.ToInt32(((Dictionary<string, object>)create.result)["instanceId"]);
395
-
396
- var createPrefab = _router.Dispatch(
397
- "prefab/create",
398
- 1,
399
- "{\"instanceId\":" + sourceId + ",\"path\":\"Assets/UcpControllerSmoke.prefab\"}"
400
- );
401
- Assert.That(createPrefab.error, Is.Null);
402
-
403
- var instantiate = _router.Dispatch(
404
- "object/instantiate",
405
- 1,
406
- "{\"prefab\":\"Assets/UcpControllerSmoke.prefab\",\"name\":\"PrefabInstance\"}"
407
- );
408
- Assert.That(instantiate.error, Is.Null);
409
- var instanceId = Convert.ToInt32(((Dictionary<string, object>)instantiate.result)["instanceId"]);
410
-
411
- var status = _router.Dispatch("prefab/status", 1, "{\"instanceId\":" + instanceId + "}");
412
- Assert.That(status.error, Is.Null);
413
- var statusResult = (Dictionary<string, object>)status.result;
414
- Assert.That(Convert.ToBoolean(statusResult["isInstance"]), Is.True);
415
-
416
- var mutate = _router.Dispatch(
417
- "object/set-property",
418
- 1,
419
- "{\"instanceId\":" + instanceId + ",\"component\":\"Transform\",\"property\":\"m_LocalPosition\",\"value\":[2,0,0]}"
420
- );
421
- Assert.That(mutate.error, Is.Null);
422
-
423
- var overrides = _router.Dispatch("prefab/overrides", 1, "{\"instanceId\":" + instanceId + "}");
424
- Assert.That(overrides.error, Is.Null);
425
- var overridesResult = (Dictionary<string, object>)overrides.result;
426
- var modifications = (List<object>)overridesResult["propertyModifications"];
427
- Assert.That(modifications.Count, Is.GreaterThanOrEqualTo(1));
428
-
429
- var unpack = _router.Dispatch("prefab/unpack", 1, "{\"instanceId\":" + instanceId + "}");
430
- Assert.That(unpack.error, Is.Null);
431
-
432
- var unpackedStatus = _router.Dispatch("prefab/status", 1, "{\"instanceId\":" + instanceId + "}");
433
- Assert.That(unpackedStatus.error, Is.Null);
434
- var unpackedStatusResult = (Dictionary<string, object>)unpackedStatus.result;
435
- Assert.That(Convert.ToBoolean(unpackedStatusResult["isInstance"]), Is.False);
436
- }
437
-
438
- [Test]
439
- public void SettingsAndBuildControllers_RoundTripWithoutSideEffects()
440
- {
441
- var playerSettings = _router.Dispatch("settings/player", 1, "{}");
442
- Assert.That(playerSettings.error, Is.Null);
443
- var settingsResult = (Dictionary<string, object>)playerSettings.result;
444
- var originalProductName = settingsResult["productName"].ToString();
445
-
446
- var setPlayer = _router.Dispatch(
447
- "settings/player-set",
448
- 1,
449
- "{\"key\":\"productName\",\"value\":\"UcpQaProduct\"}"
450
- );
451
- Assert.That(setPlayer.error, Is.Null);
452
-
453
- var verifyPlayer = _router.Dispatch("settings/player", 1, "{}");
454
- Assert.That(verifyPlayer.error, Is.Null);
455
- var verifyResult = (Dictionary<string, object>)verifyPlayer.result;
456
- Assert.That(verifyResult["productName"].ToString(), Is.EqualTo("UcpQaProduct"));
457
-
458
- var restorePlayer = _router.Dispatch(
459
- "settings/player-set",
460
- 1,
461
- "{\"key\":\"productName\",\"value\":\"" + originalProductName + "\"}"
462
- );
463
- Assert.That(restorePlayer.error, Is.Null);
464
-
465
- var scenes = _router.Dispatch("build/scenes", 1, "{}");
466
- Assert.That(scenes.error, Is.Null);
467
- var scenesResult = (Dictionary<string, object>)scenes.result;
468
- var currentScenes = (List<object>)scenesResult["scenes"];
469
- Assert.That(currentScenes.Count, Is.GreaterThanOrEqualTo(1));
470
-
471
- var firstScene = (Dictionary<string, object>)currentScenes[0];
472
- var firstScenePath = firstScene["path"].ToString();
473
-
474
- var setScenes = _router.Dispatch(
475
- "build/set-scenes",
476
- 1,
477
- "{\"scenes\":[\"" + EscapeForJson(firstScenePath) + "\"]}"
478
- );
479
- Assert.That(setScenes.error, Is.Null);
480
-
481
- var defines = _router.Dispatch("build/defines", 1, "{}");
482
- Assert.That(defines.error, Is.Null);
483
- var definesResult = (Dictionary<string, object>)defines.result;
484
- var originalDefines = definesResult["defines"].ToString();
485
-
486
- var setDefines = _router.Dispatch("build/set-defines", 1, "{\"defines\":\"" + EscapeForJson(originalDefines) + "\"}");
487
- Assert.That(setDefines.error, Is.Null);
488
- }
489
-
490
- private static void DeleteTempAsset()
491
- {
492
- if (AssetDatabase.LoadMainAssetAtPath(TempAssetPath) != null)
493
- {
494
- AssetDatabase.DeleteAsset(TempAssetPath);
495
- AssetDatabase.SaveAssets();
496
- }
497
- }
498
-
499
- private static void DeleteTempReferenceAsset()
500
- {
501
- if (AssetDatabase.LoadMainAssetAtPath(TempReferenceAssetPath) != null)
502
- {
503
- AssetDatabase.DeleteAsset(TempReferenceAssetPath);
504
- AssetDatabase.SaveAssets();
505
- }
506
- }
507
-
508
- private static void DeleteTempPrefab()
509
- {
510
- if (AssetDatabase.LoadMainAssetAtPath(TempPrefabPath) != null)
511
- {
512
- AssetDatabase.DeleteAsset(TempPrefabPath);
513
- AssetDatabase.SaveAssets();
514
- }
515
- }
516
-
517
- private static void DeleteTempMaterial()
518
- {
519
- if (AssetDatabase.LoadMainAssetAtPath(TempMaterialPath) != null)
520
- {
521
- AssetDatabase.DeleteAsset(TempMaterialPath);
522
- AssetDatabase.SaveAssets();
523
- }
524
- }
525
-
526
- private static void DeleteTempTextFile()
527
- {
528
- if (AssetDatabase.LoadMainAssetAtPath(TempTextPath) != null)
529
- {
530
- AssetDatabase.DeleteAsset(TempTextPath);
531
- AssetDatabase.SaveAssets();
532
- }
533
- }
534
-
535
- private static string FindFirstFloatOrRangeProperty(Shader shader)
536
- {
537
- for (var index = 0; index < shader.GetPropertyCount(); index++)
538
- {
539
- var propertyType = shader.GetPropertyType(index);
540
- if (propertyType == UnityEngine.Rendering.ShaderPropertyType.Float
541
- || propertyType == UnityEngine.Rendering.ShaderPropertyType.Range)
542
- {
543
- return shader.GetPropertyName(index);
544
- }
545
- }
546
-
547
- return null;
548
- }
549
-
550
- private static string EscapeForJson(string value)
551
- {
552
- return value
553
- .Replace("\\", "\\\\")
554
- .Replace("\"", "\\\"");
555
- }
556
-
557
- private static Dictionary<string, object> FindAssetMatch(List<object> matches, string expectedPath, string expectedName)
558
- {
559
- foreach (var entry in matches)
560
- {
561
- var match = (Dictionary<string, object>)entry;
562
- var path = match.ContainsKey("path") ? match["path"].ToString() : string.Empty;
563
- var name = match.ContainsKey("name") ? match["name"].ToString() : string.Empty;
564
- if (path == expectedPath && name == expectedName)
565
- return match;
566
- }
567
-
568
- return null;
569
- }
570
-
571
- private sealed class SearchRootAsset : ScriptableObject
572
- {
573
- }
574
-
575
- private sealed class SearchNestedAsset : ScriptableObject
576
- {
577
- }
578
-
579
- private sealed class BatchWritableAsset : ScriptableObject
580
- {
581
- public int maxPlayers;
582
- public float spawnDelay;
583
- public SearchRootAsset referenceAsset;
584
- }
585
-
586
- private sealed class ReferenceComponent : MonoBehaviour
587
- {
588
- public SearchRootAsset referenceAsset;
589
- }
590
- }
591
- }
@@ -1,2 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: 600e32c699a40d649ac399a646914084
@@ -1,12 +0,0 @@
1
- {
2
- "name": "UCP.Bridge.Editor.Tests",
3
- "references": [
4
- "UCP.Bridge.Editor"
5
- ],
6
- "includePlatforms": [
7
- "Editor"
8
- ],
9
- "optionalUnityReferences": [
10
- "TestAssemblies"
11
- ]
12
- }
@@ -1,7 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: 02e7b7caa7f5b1d4f8b6fe3c2eec4a9a
3
- AssemblyDefinitionImporter:
4
- externalObjects: {}
5
- userData:
6
- assetBundleName:
7
- assetBundleVariant:
@@ -1,8 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: 19eb519a09014fb488bba8c69e67b77f
3
- folderAsset: yes
4
- DefaultImporter:
5
- externalObjects: {}
6
- userData:
7
- assetBundleName:
8
- assetBundleVariant:
@@ -1,8 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: fe1724a7076470544ae5120d40748fa1
3
- folderAsset: yes
4
- DefaultImporter:
5
- externalObjects: {}
6
- userData:
7
- assetBundleName:
8
- assetBundleVariant:
@@ -1,27 +0,0 @@
1
- {
2
- "name": "com.ucp.bridge",
3
- "version": "0.3.3",
4
- "displayName": "Unity Control Protocol Bridge",
5
- "description": "WebSocket bridge for programmatic Unity Editor control via CLI and AI agents.",
6
- "unity": "2021.3",
7
- "keywords": [
8
- "automation",
9
- "devtools",
10
- "bridge",
11
- "cli",
12
- "agent"
13
- ],
14
- "author": {
15
- "name": "UCP Contributors",
16
- "url": "https://github.com/mflRevan/unity-control-protocol"
17
- },
18
- "license": "MIT",
19
- "repository": {
20
- "type": "git",
21
- "url": "https://github.com/mflRevan/unity-control-protocol.git"
22
- },
23
- "type": "tool",
24
- "documentationUrl": "https://github.com/mflRevan/unity-control-protocol/blob/main/README.md",
25
- "changelogUrl": "https://github.com/mflRevan/unity-control-protocol/blob/main/unity-package/com.ucp.bridge/CHANGELOG.md",
26
- "dependencies": {}
27
- }
@@ -1,7 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: e34242c72ce53964ab5f62878433f5b6
3
- PackageManifestImporter:
4
- externalObjects: {}
5
- userData:
6
- assetBundleName:
7
- assetBundleVariant: