7ecf0d53bd
checkpoint / checkpoint (push) Failing after 3h14m9s
- Creator Studio: Visual behavior & property inspector, GLB model importer, binary persistence - Trust & Safety: 18+ TOS confirmation (DOB removed), creator guidelines & briefing card on join, in-game reporting HUD - Test Harness: Add --filter, --skip-backend, --skip-godot to run_checkpoint_tests.py
153 lines
5.2 KiB
GDScript
153 lines
5.2 KiB
GDScript
extends SceneTree
|
|
## Headless smoke test for Creator Studio Visual Property & Behavior Inspector
|
|
|
|
const FIXTURE_PATH := "res://backend/tests/fixtures/chunks/simple_tile_chunk.bin"
|
|
const ChunkEditorModelClass := preload("res://scripts/editor/chunk_editor_model.gd")
|
|
const EditorObjectCatalogClass := preload("res://scripts/editor/object_catalog.gd")
|
|
const EditorCoreClass := preload("res://scripts/editor/editor_core.gd")
|
|
const InspectorPanelClass := preload("res://scripts/editor/ui/inspector_panel.gd")
|
|
const StaticObjectNodeClass := preload("res://scripts/static_object_node.gd")
|
|
const WorldObjectClass := preload("res://scripts/world_object.gd")
|
|
const ChunkDataDecoderClass := preload("res://scripts/chunk_data_decoder.gd")
|
|
|
|
var passed := 0
|
|
var failed := 0
|
|
|
|
func _check(label: String, cond: bool) -> void:
|
|
if cond:
|
|
passed += 1
|
|
print(" PASS: ", label)
|
|
else:
|
|
failed += 1
|
|
printerr(" FAIL: ", label)
|
|
|
|
|
|
func _initialize() -> void:
|
|
await _run()
|
|
|
|
|
|
func _read_fixture() -> PackedByteArray:
|
|
var f := FileAccess.open(FIXTURE_PATH, FileAccess.READ)
|
|
if f == null:
|
|
push_error("Could not open fixture: " + FIXTURE_PATH)
|
|
return PackedByteArray()
|
|
return f.get_buffer(f.get_length())
|
|
|
|
|
|
func _run() -> void:
|
|
print("=== Running Creator Studio Inspector & Behavior Smoke Tests ===")
|
|
var root := Node.new()
|
|
root.name = "TestRoot"
|
|
get_root().add_child(root)
|
|
|
|
var fixture_bytes := _read_fixture()
|
|
_check("Loaded fixture binary bytes", fixture_bytes.size() > 0)
|
|
if fixture_bytes.is_empty():
|
|
quit(1)
|
|
return
|
|
|
|
var model := ChunkEditorModelClass.from_binary(fixture_bytes)
|
|
_check("Decoded ChunkEditorModel from binary", model != null)
|
|
|
|
var catalog := EditorObjectCatalogClass.new()
|
|
var cat_err := catalog.load_catalog()
|
|
_check("Loaded EditorObjectCatalog", cat_err == OK)
|
|
|
|
var core := EditorCoreClass.new(model, catalog)
|
|
_check("Initialized EditorCore", core != null)
|
|
|
|
# 1. Place an object
|
|
var obj_id := core.place_object("crate_small", Vector3(1.0, 1.0, 0.0))
|
|
_check("Placed object via EditorCore", obj_id != "")
|
|
var obj := model.find_object(obj_id)
|
|
_check("Object found in model", obj != null)
|
|
|
|
# 2. Attach and verify InspectorPanel
|
|
var inspector := InspectorPanelClass.new()
|
|
root.add_child(inspector)
|
|
await process_frame
|
|
inspector.setup(core)
|
|
inspector.show_object(obj_id)
|
|
_check("InspectorPanel loaded object view", true)
|
|
|
|
# 3. Add behavior rules to object
|
|
var test_behavior: Dictionary = {
|
|
"rules": [
|
|
{
|
|
"trigger": {"type": "on_interact"},
|
|
"conditions": [],
|
|
"actions": [
|
|
{"verb": "give_item", "item_id": "buffalo_chips", "count": 10}
|
|
]
|
|
},
|
|
{
|
|
"trigger": {"type": "on_timer", "interval": 1.5},
|
|
"conditions": [],
|
|
"actions": [
|
|
{"verb": "rotate", "degrees": 90.0, "axis": "y", "duration": 0.4}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
var set_ok := core.set_object_behavior(obj_id, test_behavior)
|
|
_check("set_object_behavior executed via ToolRegistry", set_ok)
|
|
_check("Object properties has script_behavior", obj.properties.has("script_behavior"))
|
|
var attached = obj.properties.get("script_behavior", {})
|
|
_check("Attached behavior contains 2 rules", attached.get("rules", []).size() == 2)
|
|
|
|
# 4. Undo and Redo verification
|
|
var undo_ok := core.undo_redo.undo()
|
|
_check("Undo executed successfully", undo_ok)
|
|
_check("Undo cleared script_behavior property", not obj.properties.has("script_behavior"))
|
|
|
|
var redo_ok := core.undo_redo.redo()
|
|
_check("Redo executed successfully", redo_ok)
|
|
_check("Redo restored script_behavior property", obj.properties.has("script_behavior"))
|
|
_check("Redo preserved both rules", obj.properties.get("script_behavior", {}).get("rules", []).size() == 2)
|
|
|
|
# 5. Roundtrip through Chunk binary encode/decode
|
|
var re_encoded := model.encode_binary()
|
|
_check("Model encoded to binary bytes with behavior", re_encoded.size() > 0)
|
|
|
|
var re_decoded := ChunkDataDecoderClass.decode_binary(re_encoded)
|
|
_check("Decoded re-encoded binary chunk", re_decoded != null)
|
|
var persisted_obj: ChunkDataDecoderClass.WorldObjectData = null
|
|
for o in re_decoded.objects:
|
|
if o.id == obj_id:
|
|
persisted_obj = o
|
|
break
|
|
_check("Persisted object found in binary decoded chunk", persisted_obj != null)
|
|
_check("Persisted object retained script_behavior rules", persisted_obj.properties.has("script_behavior"))
|
|
|
|
# 6. StaticObjectNode & ScriptInterpreterNode verification
|
|
var wo := WorldObjectClass.new()
|
|
wo.id = obj.id
|
|
wo.type = obj.type
|
|
wo.asset_id = obj.asset_id
|
|
wo.position = obj.position
|
|
wo.rotation = obj.rotation
|
|
wo.scale = obj.scale
|
|
wo.properties = obj.properties.duplicate(true)
|
|
|
|
var static_node := StaticObjectNodeClass.new()
|
|
static_node.world_object = wo
|
|
root.add_child(static_node)
|
|
await process_frame
|
|
|
|
var interpreter := static_node.get_node_or_null("ScriptInterpreter")
|
|
_check("StaticObjectNode created ScriptInterpreter child", interpreter != null)
|
|
if interpreter != null:
|
|
_check("ScriptInterpreter parsed valid behavior", interpreter.behavior != null)
|
|
if interpreter.behavior != null:
|
|
_check("ScriptInterpreter rules count is 2", interpreter.behavior.rules.size() == 2)
|
|
|
|
# Refresh inspector display with rules
|
|
inspector.show_object(obj_id)
|
|
_check("Inspector refreshed object display", true)
|
|
|
|
print("Smoke test complete. Passed: %d, Failed: %d" % [passed, failed])
|
|
if failed > 0:
|
|
quit(1)
|
|
else:
|
|
quit(0)
|