blob: a66790046d1e454bd89440f96cc33d6791e83eea [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/vr/elements/transient_element.h"
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "chrome/browser/vr/test/animation_utils.h"
#include "chrome/browser/vr/test/constants.h"
#include "chrome/browser/vr/ui_scene.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace vr {
TEST(SimpleTransientElementTest, Visibility) {
SimpleTransientElement element(base::TimeDelta::FromSeconds(2));
element.SetOpacity(0.0f);
EXPECT_EQ(0.0f, element.opacity());
// Enable and disable, making sure the element appears and disappears.
element.SetVisible(true);
EXPECT_EQ(element.opacity_when_visible(), element.opacity());
element.SetVisible(false);
EXPECT_EQ(0.0f, element.opacity());
// Enable, and ensure that the element transiently disappears.
element.SetVisible(true);
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(0), kForwardVector));
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(10), kForwardVector));
EXPECT_EQ(element.opacity_when_visible(), element.opacity());
EXPECT_TRUE(element.DoBeginFrame(MsToTicks(2010), kForwardVector));
EXPECT_EQ(0.0f, element.opacity());
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(2020), kForwardVector));
// Enable, and ensure that the element transiently disappears using
// SetVisibleImmediately.
element.SetVisibleImmediately(true);
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(2020), kForwardVector));
EXPECT_EQ(element.opacity_when_visible(), element.opacity());
EXPECT_TRUE(element.DoBeginFrame(MsToTicks(4020), kForwardVector));
EXPECT_EQ(0.0f, element.opacity());
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(4030), kForwardVector));
element.SetTransitionedProperties({OPACITY});
element.SetVisible(true);
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(4030), kForwardVector));
EXPECT_NE(element.opacity_when_visible(), element.opacity());
element.SetVisibleImmediately(true);
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(4030), kForwardVector));
EXPECT_EQ(element.opacity_when_visible(), element.opacity());
EXPECT_TRUE(element.DoBeginFrame(MsToTicks(6060), kForwardVector));
EXPECT_EQ(0.0f, element.GetTargetOpacity());
}
// Test that refreshing the visibility resets the transience timeout if the
// element is currently visible.
TEST(SimpleTransientElementTest, RefreshVisibility) {
SimpleTransientElement element(base::TimeDelta::FromSeconds(2));
element.SetOpacity(0.0f);
// Enable, and ensure that the element is visible.
element.SetVisible(true);
EXPECT_EQ(element.opacity_when_visible(), element.opacity());
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(0), kForwardVector));
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(1000), kForwardVector));
// Refresh visibility, and ensure that the element still transiently
// disappears, but at a later time.
element.RefreshVisible();
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(1000), kForwardVector));
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(2000), kForwardVector));
EXPECT_EQ(element.opacity_when_visible(), element.opacity());
EXPECT_TRUE(element.DoBeginFrame(MsToTicks(3000), kForwardVector));
EXPECT_EQ(0.0f, element.opacity());
// Refresh visibility, and ensure that disabling hides the element.
element.SetVisible(true);
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(3000), kForwardVector));
EXPECT_EQ(element.opacity_when_visible(), element.opacity());
element.RefreshVisible();
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(3000), kForwardVector));
EXPECT_FALSE(element.DoBeginFrame(MsToTicks(4000), kForwardVector));
EXPECT_EQ(element.opacity_when_visible(), element.opacity());
element.SetVisible(false);
EXPECT_EQ(0.0f, element.opacity());
}
// Test that changing visibility on transient parent has the same effect on its
// children.
// TODO(mthiesse, vollick): Convert this test to use bindings.
TEST(SimpleTransientElementTest, VisibilityChildren) {
UiScene scene;
// Create transient root.
auto transient_element =
base::MakeUnique<SimpleTransientElement>(base::TimeDelta::FromSeconds(2));
SimpleTransientElement* parent = transient_element.get();
transient_element->set_opacity_when_visible(0.5);
scene.AddUiElement(kRoot, std::move(transient_element));
// Create child.
auto element = base::MakeUnique<UiElement>();
UiElement* child = element.get();
element->set_opacity_when_visible(0.5);
element->SetVisible(true);
parent->AddChild(std::move(element));
// Child hidden because parent is hidden.
EXPECT_TRUE(scene.OnBeginFrame(MsToTicks(0), kForwardVector));
EXPECT_FALSE(child->IsVisible());
EXPECT_FALSE(parent->IsVisible());
// Setting visiblity on parent should make the child visible.
parent->SetVisible(true);
scene.set_dirty();
EXPECT_TRUE(scene.OnBeginFrame(MsToTicks(10), kForwardVector));
EXPECT_TRUE(child->IsVisible());
EXPECT_TRUE(parent->IsVisible());
// Make sure the elements go away.
EXPECT_TRUE(scene.OnBeginFrame(MsToTicks(2010), kForwardVector));
EXPECT_FALSE(child->IsVisible());
EXPECT_FALSE(parent->IsVisible());
// Test again, but this time manually set the visibility to false.
parent->SetVisible(true);
scene.set_dirty();
EXPECT_TRUE(scene.OnBeginFrame(MsToTicks(2020), kForwardVector));
EXPECT_TRUE(child->IsVisible());
EXPECT_TRUE(parent->IsVisible());
parent->SetVisible(false);
scene.set_dirty();
EXPECT_TRUE(scene.OnBeginFrame(MsToTicks(2030), kForwardVector));
EXPECT_FALSE(child->IsVisible());
EXPECT_FALSE(parent->IsVisible());
}
class ShowUntilSignalElementTest : public testing::Test {
public:
ShowUntilSignalElementTest() {}
void SetUp() override {
callback_triggered_ = false;
element_ = base::MakeUnique<ShowUntilSignalTransientElement>(
base::TimeDelta::FromSeconds(2), base::TimeDelta::FromSeconds(5),
base::Bind(&ShowUntilSignalElementTest::OnTimeout,
base::Unretained(this)));
}
ShowUntilSignalTransientElement& element() { return *element_; }
TransientElementHideReason hide_reason() { return hide_reason_; }
bool callback_triggered() { return callback_triggered_; }
void OnTimeout(TransientElementHideReason reason) {
callback_triggered_ = true;
hide_reason_ = reason;
}
private:
bool callback_triggered_ = false;
TransientElementHideReason hide_reason_;
std::unique_ptr<ShowUntilSignalTransientElement> element_;
};
// Test that the element disappears when signalled.
TEST_F(ShowUntilSignalElementTest, ElementHidesAfterSignal) {
EXPECT_FALSE(element().IsVisible());
// Make element visible.
element().SetVisible(true);
EXPECT_FALSE(element().DoBeginFrame(MsToTicks(10), kForwardVector));
EXPECT_EQ(element().opacity_when_visible(), element().opacity());
// Signal, element should still be visible since time < min duration.
element().Signal(true);
EXPECT_FALSE(element().DoBeginFrame(MsToTicks(200), kForwardVector));
EXPECT_EQ(element().opacity_when_visible(), element().opacity());
// Element hides and callback triggered.
EXPECT_TRUE(element().DoBeginFrame(MsToTicks(2010), kForwardVector));
EXPECT_EQ(0.0f, element().opacity());
EXPECT_TRUE(callback_triggered());
EXPECT_EQ(TransientElementHideReason::kSignal, hide_reason());
}
// Test that the transient element times out.
TEST_F(ShowUntilSignalElementTest, TimedOut) {
EXPECT_FALSE(element().IsVisible());
// Make element visible.
element().SetVisible(true);
EXPECT_FALSE(element().DoBeginFrame(MsToTicks(10), kForwardVector));
EXPECT_EQ(element().opacity_when_visible(), element().opacity());
// Element should be visible since we haven't signalled.
EXPECT_FALSE(element().DoBeginFrame(MsToTicks(2010), kForwardVector));
EXPECT_EQ(element().opacity_when_visible(), element().opacity());
// Element hides and callback triggered.
EXPECT_TRUE(element().DoBeginFrame(MsToTicks(6010), kForwardVector));
EXPECT_EQ(0.0f, element().opacity());
EXPECT_TRUE(callback_triggered());
EXPECT_EQ(TransientElementHideReason::kTimeout, hide_reason());
}
// Test that refreshing the visibility resets the transience timeout if the
// element is currently visible.
TEST_F(ShowUntilSignalElementTest, RefreshVisibility) {
// Enable, and ensure that the element is visible.
element().SetVisible(true);
EXPECT_EQ(element().opacity_when_visible(), element().opacity());
EXPECT_FALSE(element().DoBeginFrame(MsToTicks(0), kForwardVector));
EXPECT_FALSE(element().DoBeginFrame(MsToTicks(1000), kForwardVector));
element().Signal(true);
// Refresh visibility, and ensure that the element still transiently
// disappears, but at a later time.
element().RefreshVisible();
EXPECT_FALSE(element().DoBeginFrame(MsToTicks(1000), kForwardVector));
EXPECT_FALSE(element().DoBeginFrame(MsToTicks(2500), kForwardVector));
EXPECT_EQ(element().opacity_when_visible(), element().opacity());
EXPECT_TRUE(element().DoBeginFrame(MsToTicks(3000), kForwardVector));
EXPECT_EQ(0.0f, element().opacity());
EXPECT_EQ(TransientElementHideReason::kSignal, hide_reason());
}
} // namespace vr