namespace SceneTests.Components;
///
/// Tests for the GetComponent family of helpers on
/// (Component.GetComponent.cs). These are shortcuts that search the component's
/// own GameObject and, depending on the call, its ancestors or descendants.
///
[TestClass]
[DoNotParallelize]
public class ComponentGetComponentTest : SceneTest
{
///
/// AddComponent on a component attaches the new component to the same
/// GameObject, and honours the startEnabled argument.
///
[TestMethod]
public void AddComponentCreatesOnOwnGameObject()
{
var scene = new Scene();
using var sceneScope = scene.Push();
var go = scene.CreateObject();
var alpha = go.Components.Create();
var beta = alpha.AddComponent();
Assert.IsNotNull( beta );
Assert.AreSame( go, beta.GameObject );
Assert.IsTrue( beta.Enabled );
var disabledBeta = alpha.AddComponent( false );
Assert.AreSame( go, disabledBeta.GameObject );
Assert.IsFalse( disabledBeta.Enabled );
}
///
/// GetOrAddComponent returns an existing component instead of creating a
/// duplicate - even when the existing component is disabled.
///
[TestMethod]
public void GetOrAddComponentReturnsExistingEvenWhenDisabled()
{
var scene = new Scene();
using var sceneScope = scene.Push();
var go = scene.CreateObject();
var alpha = go.Components.Create();
var beta = go.Components.Create( false );
var fetched = alpha.GetOrAddComponent();
Assert.AreSame( beta, fetched );
Assert.AreEqual( 1, go.Components.GetAll( FindMode.EverythingInSelf ).Count() );
}
///
/// GetOrAddComponent creates the component when none exists, and a second
/// call returns that same instance.
///
[TestMethod]
public void GetOrAddComponentCreatesWhenMissing()
{
var scene = new Scene();
using var sceneScope = scene.Push();
var go = scene.CreateObject();
var alpha = go.Components.Create();
var created = alpha.GetOrAddComponent();
Assert.IsNotNull( created );
Assert.AreSame( go, created.GameObject );
Assert.AreSame( created, alpha.GetOrAddComponent() );
}
///
/// GetComponent skips disabled components by default, and finds them when
/// includeDisabled is passed.
///
[TestMethod]
public void GetComponentHonoursIncludeDisabled()
{
var scene = new Scene();
using var sceneScope = scene.Push();
var go = scene.CreateObject();
var alpha = go.Components.Create();
var beta = go.Components.Create( false );
Assert.IsNull( alpha.GetComponent() );
Assert.AreSame( beta, alpha.GetComponent( true ) );
}
///
/// GetComponents only searches the component's own GameObject - children are
/// never included - and only includes disabled components when asked to.
///
[TestMethod]
public void GetComponentsSearchesSelfOnly()
{
var scene = new Scene();
using var sceneScope = scene.Push();
var go = scene.CreateObject();
var alpha = go.Components.Create();
go.Components.Create();
go.Components.Create( false );
var child = new GameObject( go, name: "Child" );
child.Components.Create();
Assert.AreEqual( 1, alpha.GetComponents().Count() );
Assert.AreEqual( 2, alpha.GetComponents( true ).Count() );
}
///
/// GetComponentsInChildren walks all descendants, optionally including the
/// component's own GameObject and disabled components.
///
[TestMethod]
public void GetComponentsInChildrenHonoursFlags()
{
var scene = new Scene();
using var sceneScope = scene.Push();
var go = scene.CreateObject();
var alpha = go.Components.Create();
go.Components.Create();
var child = new GameObject( go, name: "Child" );
child.Components.Create();
var grandChild = new GameObject( child, name: "GrandChild" );
grandChild.Components.Create( false );
// self + child, the disabled grandchild component is skipped
Assert.AreEqual( 2, alpha.GetComponentsInChildren().Count() );
// child only
Assert.AreEqual( 1, alpha.GetComponentsInChildren( includeSelf: false ).Count() );
// self + child + disabled grandchild
Assert.AreEqual( 3, alpha.GetComponentsInChildren( includeDisabled: true ).Count() );
// the single version finds one too
Assert.IsNotNull( alpha.GetComponentInChildren() );
Assert.IsNull( alpha.GetComponentInChildren( includeSelf: false ) );
}
///
/// GetComponentInParent prefers a component on the own GameObject when
/// includeSelf is true, and skips to the ancestors when it's false.
/// GetComponentsInParent collects from the whole ancestor chain.
///
[TestMethod]
public void GetComponentInParentHonoursIncludeSelf()
{
var scene = new Scene();
using var sceneScope = scene.Push();
var parent = scene.CreateObject();
var parentAlpha = parent.Components.Create();
parent.Components.Create( false );
var self = new GameObject( parent, name: "Self" );
var selfAlpha = self.Components.Create();
var anchor = self.Components.Create();
Assert.AreSame( selfAlpha, anchor.GetComponentInParent() );
Assert.AreSame( parentAlpha, anchor.GetComponentInParent( includeSelf: false ) );
// self enabled + parent enabled
Assert.AreEqual( 2, anchor.GetComponentsInParent().Count() );
// parent enabled + parent disabled
Assert.AreEqual( 2, anchor.GetComponentsInParent( includeDisabled: true, includeSelf: false ).Count() );
}
}
///
/// Plain component used as a search target in GetComponent tests.
///
public class GetAlphaComponent : Component
{
}
///
/// Second plain component type used as a search target in GetComponent tests.
///
public class GetBetaComponent : Component
{
}