    use crate::assets::EditorAsset;
    use crate::history::{apply_command_undo, EditorHistory};
    use crate::ui::{DockTabRequest, UiState};

    #[test]
    fn component_collapse_persists_while_ui_state_is_scoped_out() {
        let mut world = World::new();
        world.init_resource::<EditorComponentRegistry>();
        world.init_resource::<InspectorPanelState>();
        let entity = world
            .spawn((ActorId::new("collapsed-component"), Transform::IDENTITY))
            .id();
        world.insert_resource(UiState::default_layout());

        world.resource_scope::<UiState, _>(|world, _ui_state| {
            assert!(!world.contains_resource::<UiState>());
            apply_component_card_response(
                world,
                entity,
                ComponentCardResponse {
                    type_name: COMPONENT_TRANSFORM,
                    collapsed: Some(true),
                    ..Default::default()
                },
            );
            let context = component_card_context(
                world,
                entity,
                ComponentCardOptions::fixed(COMPONENT_TRANSFORM, "Transform", icons::CUBE),
            );
            assert!(context.collapsed);
        });
    }

    #[test]
    fn locate_texture_requests_asset_browser_while_ui_state_is_scoped_out() {
        let path = "assets/textures/scoped-locate.png";
        let folder = "assets/textures";
        let selection = AssetSelection::File(path.to_string());
        let mut world = World::new();
        world.insert_resource(EditorAssets {
            folders: Vec::new(),
            assets: vec![EditorAsset {
                label: "Scoped Locate".into(),
                path: Some(path.into()),
                folder_path: folder.into(),
                kind: EditorAssetKind::Texture,
            }],
            current_folder: crate::assets::ASSETS_ROOT.into(),
            selected: None,
            selections: Vec::new(),
            selection_anchor: None,
            dragging: None,
            status: String::new(),
            catalog_revision: 1,
        });
        world.init_resource::<DockTabRequest>();
        world.insert_resource(UiState::default_layout());
        let candidate = TextureAssetCandidate {
            label: "Scoped Locate".into(),
            path: path.into(),
            folder_path: folder.into(),
            selection: selection.clone(),
            texture_id: None,
        };

        world.resource_scope::<UiState, _>(|world, _ui_state| {
            assert!(!world.contains_resource::<UiState>());
            locate_texture_asset(world, Some(path), &[candidate]);
        });

        let assets = world.resource::<EditorAssets>();
        assert_eq!(assets.current_folder, folder);
        assert_eq!(assets.selected.as_ref(), Some(&selection));
        assert_eq!(
            world.resource::<DockTabRequest>().0,
            Some(EditorTab::AssetBrowser)
        );
    }

    #[test]
    fn shape_switch_preserves_dimensions_and_is_one_undoable_edit() {
        let mut world = World::new();
        world.init_resource::<EditorHistory>();
        let original = ColliderDesc::static_cuboid(Vec3::new(2.0, 4.0, 6.0));
        let entity = world.spawn((LevelObject, original.clone())).id();

        let sphere = ColliderDesc {
            shape: convert_collider_shape(&original.shape, "Sphere", Vec::new()),
            ..original.clone()
        };
        assert_eq!(sphere.shape, ColliderShapeDesc::Sphere { radius: 3.0 });

        set_collider_with_history(&mut world, entity, sphere.clone());
        assert_eq!(world.resource::<EditorHistory>().undo_depth(), 1);
        assert_eq!(world.get::<ColliderDesc>(entity), Some(&sphere));

        apply_command_undo(&mut world);
        assert_eq!(world.get::<ColliderDesc>(entity), Some(&original));
    }

    fn promotion_test_root(label: &str) -> PathBuf {
        let nonce = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_nanos();
        std::env::temp_dir().join(format!(
            "blacksite-property-promotion-{label}-{}-{nonce}",
            std::process::id()
        ))
    }

    fn promotion_test_world(
        root: &Path,
    ) -> (
        App,
        Entity,
        ComponentInstanceId,
        MaterialRef,
        MaterialPropertyBlock,
    ) {
        let material_folder = root.join("assets/materials");
        std::fs::create_dir_all(&material_folder).unwrap();
        let base_reference = MaterialRef::new(
            EditorAssetRef::new("material-id", "material:source", "Promotion Base")
                .with_source_path("assets/materials/promotion_base.ron"),
        );
        let base_asset = MaterialAsset {
            schema_version: shared::MATERIAL_ASSET_SCHEMA_VERSION,
            label: "Promotion Base".into(),
            shader: shared::ShaderRefDesc::default(),
            shader_ref: None,
            render_state: shared::MaterialRenderState::default(),
            provenance: None,
            inputs: shared::MaterialInputSet::default(),
        };
        std::fs::write(
            material_folder.join("promotion_base.ron"),
            ron::ser::to_string_pretty(&base_asset, ron::ser::PrettyConfig::default()).unwrap(),
        )
        .unwrap();
        let selected_reference = MaterialRef::new(
            EditorAssetRef::new("instance-id", "material:instance", "Promotion Variant")
                .with_source_path("assets/materials/promotion_variant.material-instance.ron"),
        );
        let selected_instance = MaterialInstanceAsset {
            schema_version: shared::MATERIAL_INSTANCE_SCHEMA_VERSION,
            label: "Promotion Variant".into(),
            base: base_reference.clone(),
            overrides: shared::MaterialInputSet {
                values: vec![MaterialParameter {
                    name: "roughness".into(),
                    value: MaterialParameterValue::Float(0.4),
                }],
                textures: Vec::new(),
            },
        };
        std::fs::write(
            material_folder.join("promotion_variant.material-instance.ron"),
            ron::ser::to_string_pretty(&selected_instance, ron::ser::PrettyConfig::default())
                .unwrap(),
        )
        .unwrap();

        let mut app = App::new();
        app.add_plugins(shared::SharedTypesPlugin);
        let world = app.world_mut();
        world.init_resource::<EditorHistory>();
        world.init_resource::<crate::scene_io::SceneIo>();
        world.insert_resource(ProjectWorkspace {
            root: root.to_string_lossy().into_owned(),
            project_id: "promotion-test".into(),
            project_kind: settings::ProjectKind::Game,
            last_opened_scene: None,
            settings_path: "assets/project.ron".into(),
            settings_dirty: false,
            layout_dirty: false,
        });
        world.insert_resource(EditorAssets {
            folders: Vec::new(),
            assets: Vec::new(),
            current_folder: "assets/materials".into(),
            selected: None,
            selections: Vec::new(),
            selection_anchor: None,
            dragging: None,
            status: String::new(),
            catalog_revision: 1,
        });
        world.insert_resource(AssetRegistry::default());
        let slot_id = ComponentInstanceId::new("slot:body");
        let renderer = StaticMeshRenderer {
            slots: Vec::new(),
            materials: shared::RendererMaterialSet {
                slots: vec![shared::RendererMaterialSlot {
                    id: slot_id.clone(),
                    name: "Body".into(),
                    material: Some(selected_reference.clone()),
                }],
                orphaned_assignments: Vec::new(),
            },
        };
        let block = MaterialPropertyBlock {
            slot_id: slot_id.clone(),
            parameters: vec![
                MaterialParameter {
                    name: "roughness".into(),
                    value: MaterialParameterValue::Float(0.8),
                },
                MaterialParameter {
                    name: "metallic".into(),
                    value: MaterialParameterValue::Float(0.2),
                },
            ],
            textures: Vec::new(),
        };
        let entity = world
            .spawn((
                LevelObject,
                ActorKind::StaticMesh,
                renderer,
                MaterialPropertyBlocks {
                    slots: vec![block.clone()],
                },
            ))
            .id();
        (app, entity, slot_id, selected_reference, block)
    }
