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 { }