/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include "LyShineTest.h" #include #include "UiGameEntityContext.h" #include "UiButtonComponent.h" #include "UiTooltipComponent.h" #include "UiTooltipDisplayComponent.h" #include "UiElementComponent.h" #include "UiTransform2dComponent.h" #include "UiCanvasComponent.h" #include "UiImageComponent.h" #include #include #include #include #include #include #include #include #include #include namespace UnitTest { struct UiTooltipTestStubTimer : public AZ::StubTimeSystem { AZ::TimeMs GetRealElapsedTimeMs() const override { m_time += AZ::TimeMs{ 1000 }; return m_time; } mutable AZ::TimeMs m_time = AZ::Time::ZeroTimeMs; }; class UiTooltipTestApplication : public AzFramework::Application { public: UiTooltipTestApplication() : AzFramework::Application() { m_timeSystem.reset(); m_timeSystem = AZStd::make_unique(); } void Reflect(AZ::ReflectContext* context) override { AzFramework::Application::Reflect(context); UiSerialize::ReflectUiTypes(context); //< needed to serialize ui Anchor and Offset } private: // override and only include system components required for tests. AZ::ComponentTypeList GetRequiredSystemComponents() const override { return AZ::ComponentTypeList{ azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), }; } void RegisterCoreComponents() override { AzFramework::Application::RegisterCoreComponents(); RegisterComponentDescriptor(UiTransform2dComponent::CreateDescriptor()); RegisterComponentDescriptor(UiElementComponent::CreateDescriptor()); RegisterComponentDescriptor(UiButtonComponent::CreateDescriptor()); RegisterComponentDescriptor(UiTooltipComponent::CreateDescriptor()); RegisterComponentDescriptor(UiTooltipDisplayComponent::CreateDescriptor()); RegisterComponentDescriptor(UiImageComponent::CreateDescriptor()); RegisterComponentDescriptor(UiCanvasComponent::CreateDescriptor()); } }; class UiTooltipComponentTest : public testing::Test { protected: UiTooltipTestApplication* m_application = nullptr; protected: void SetUp() override { // start application AZ::AllocatorInstance::Create(AZ::SystemAllocator::Descriptor()); AZ::ComponentApplication::Descriptor appDescriptor; appDescriptor.m_useExistingAllocator = true; m_application = aznew UiTooltipTestApplication(); m_application->Start(appDescriptor, AZ::ComponentApplication::StartupParameters()); } void TearDown() override { m_application->Stop(); delete m_application; m_application = nullptr; AZ::AllocatorInstance::Destroy(); } AZStd::tuple CreateUiCanvasWithTooltip() { // create a canvas UiGameEntityContext* entityContext = new UiGameEntityContext(); //< UiCanvasComponent takes ownership of this pointer and will free this when exiting UiCanvasComponent* uiCanvasComponent = UiCanvasComponent::CreateCanvasInternal(entityContext, false); // add scroll bar to the canvas AZ::Entity* tooltipDisplayEntity = uiCanvasComponent->CreateChildElement("Ui Tooltip"); tooltipDisplayEntity->Deactivate(); //< deactivate so that we can add components tooltipDisplayEntity->CreateComponent(); //< required by UiTooltipDisplauComponent tooltipDisplayEntity->CreateComponent(); //< required by UiTooltipDisplayComponent auto uiTooltipDisplayComponent = tooltipDisplayEntity->CreateComponent(); tooltipDisplayEntity->Activate(); uiCanvasComponent->SetTooltipDisplayElement(tooltipDisplayEntity->GetId()); // create the button entity AZ::Entity* buttonEntity = uiCanvasComponent->CreateChildElement("Ui Button"); buttonEntity->Deactivate(); // deactivate to add component buttonEntity->CreateComponent(); buttonEntity->CreateComponent(); buttonEntity->CreateComponent(); auto uiTooltipComponent = buttonEntity->CreateComponent(); buttonEntity->Activate(); return AZStd::make_tuple(uiCanvasComponent, uiTooltipDisplayComponent, uiTooltipComponent); } }; TEST_F(UiTooltipComponentTest, UiTooltipComponent_WillAppearOnHover) { SSystemGlobalEnvironment env; SSystemGlobalEnvironment* prevEnv = gEnv; gEnv = &env; gEnv->pLyShine = nullptr; auto [uiCanvasComponent, uiTooltipDisplayComponent, uiTooltipComponent] = CreateUiCanvasWithTooltip(); uiTooltipDisplayComponent->SetTriggerMode(UiTooltipDisplayInterface::TriggerMode::OnHover); AZ::Entity* uiTooltipEntity = uiTooltipComponent->GetEntity(); // test: verify tooltip is hidden by default, hover over button for tooltip to appear, hover off for tooltip to disappear EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); UiInteractableNotificationBus::Event(uiTooltipEntity->GetId(), &UiInteractableNotificationBus::Events::OnHoverStart); AZ::EntityId canvasEntityId; UiElementBus::EventResult(canvasEntityId, uiTooltipComponent->GetEntityId(), &UiElementBus::Events::GetCanvasEntityId); uiTooltipDisplayComponent->Update(); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Shown); UiInteractableNotificationBus::Event(uiTooltipEntity->GetId(), &UiInteractableNotificationBus::Events::OnHoverEnd); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); // clean up the canvas delete uiCanvasComponent->GetEntity(); gEnv = prevEnv; } TEST_F(UiTooltipComponentTest, UiTooltipComponent_HoverTooltipDisappearsOnPress) { SSystemGlobalEnvironment env; SSystemGlobalEnvironment* prevEnv = gEnv; gEnv = &env; gEnv->pLyShine = nullptr; auto [uiCanvasComponent, uiTooltipDisplayComponent, uiTooltipComponent] = CreateUiCanvasWithTooltip(); uiTooltipDisplayComponent->SetTriggerMode(UiTooltipDisplayInterface::TriggerMode::OnHover); AZ::Entity* uiTooltipEntity = uiTooltipComponent->GetEntity(); // test: verify tooltip is hidden by default, hover over button for tooltip to appear, press button for tooltip to disappear EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); UiInteractableNotificationBus::Event(uiTooltipEntity->GetId(), &UiInteractableNotificationBus::Events::OnHoverStart); uiTooltipDisplayComponent->Update(); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Shown); UiInteractableNotificationBus::Event(uiTooltipEntity->GetId(), &UiInteractableNotificationBus::Events::OnPressed); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); // clean up the canvas delete uiCanvasComponent->GetEntity(); gEnv = prevEnv; } TEST_F(UiTooltipComponentTest, UiTooltipComponent_TooltipAppearsOnPress) { SSystemGlobalEnvironment env; SSystemGlobalEnvironment* prevEnv = gEnv; gEnv = &env; gEnv->pLyShine = nullptr; auto [uiCanvasComponent, uiTooltipDisplayComponent, uiTooltipComponent] = CreateUiCanvasWithTooltip(); uiTooltipDisplayComponent->SetTriggerMode(UiTooltipDisplayInterface::TriggerMode::OnPress); AZ::Entity* uiTooltipEntity = uiTooltipComponent->GetEntity(); // test: verify tooltip is hidden by default, press button for tooltip to appear, release button for tooltip to disappear EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); UiInteractableNotificationBus::Event(uiTooltipEntity->GetId(), &UiInteractableNotificationBus::Events::OnPressed); uiTooltipDisplayComponent->Update(); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Shown); UiInteractableNotificationBus::Event(uiTooltipEntity->GetId(), &UiInteractableNotificationBus::Events::OnReleased); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); // clean up the canvas delete uiCanvasComponent->GetEntity(); gEnv = prevEnv; } TEST_F(UiTooltipComponentTest, UiTooltipComponent_TooltipDisappearsOnCanvasPrimaryRelease) { SSystemGlobalEnvironment env; SSystemGlobalEnvironment* prevEnv = gEnv; gEnv = &env; gEnv->pLyShine = nullptr; auto [uiCanvasComponent, uiTooltipDisplayComponent, uiTooltipComponent] = CreateUiCanvasWithTooltip(); uiTooltipDisplayComponent->SetTriggerMode(UiTooltipDisplayInterface::TriggerMode::OnPress); AZ::Entity* uiTooltipEntity = uiTooltipComponent->GetEntity(); // test: verify tooltip is hidden by default, press button for tooltip to appear, release mouse on canvas (not on button) for tooltip to disappear EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); UiInteractableNotificationBus::Event(uiTooltipEntity->GetId(), &UiInteractableNotificationBus::Events::OnPressed); uiTooltipDisplayComponent->Update(); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Shown); UiCanvasInputNotificationBus::Event(uiCanvasComponent->GetEntityId(), &UiCanvasInputNotificationBus::Events::OnCanvasPrimaryReleased, uiCanvasComponent->GetEntityId()); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); // clean up the canvas delete uiCanvasComponent->GetEntity(); gEnv = prevEnv; } TEST_F(UiTooltipComponentTest, UiTooltipComponent_TooltipAppearsOnClick) { SSystemGlobalEnvironment env; SSystemGlobalEnvironment* prevEnv = gEnv; gEnv = &env; gEnv->pLyShine = nullptr; auto [uiCanvasComponent, uiTooltipDisplayComponent, uiTooltipComponent] = CreateUiCanvasWithTooltip(); uiTooltipDisplayComponent->SetTriggerMode(UiTooltipDisplayInterface::TriggerMode::OnClick); AZ::Entity* uiTooltipEntity = uiTooltipComponent->GetEntity(); // test: verify tooltip is hidden by default, click button for tooltip to appear, click off of button for tooltip to disappear EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); UiInteractableNotificationBus::Event(uiTooltipEntity->GetId(), &UiInteractableNotificationBus::Events::OnPressed); UiInteractableNotificationBus::Event(uiTooltipEntity->GetId(), &UiInteractableNotificationBus::Events::OnReleased); uiTooltipDisplayComponent->Update(); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Shown); UiCanvasInputNotificationBus::Event(uiCanvasComponent->GetEntityId(), &UiCanvasInputNotificationBus::Events::OnCanvasPrimaryReleased, uiCanvasComponent->GetEntityId()); EXPECT_EQ(uiTooltipDisplayComponent->GetState(), UiTooltipDisplayComponent::State::Hidden); // clean up the canvas delete uiCanvasComponent->GetEntity(); gEnv = prevEnv; } } //namespace UnitTest