blob: c9d21b5df15f48a0539e814e45b41d69cb341b5b [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 "third_party/blink/renderer/modules/media_controls/elements/media_control_loading_panel_element.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
class MediaControlLoadingPanelElementTest : public PageTestBase {
public:
void SetUp() final {
// Create page and add a video element with controls.
PageTestBase::SetUp();
media_element_ = MakeGarbageCollected<HTMLVideoElement>(GetDocument());
media_element_->SetBooleanAttribute(html_names::kControlsAttr, true);
GetDocument().body()->AppendChild(media_element_);
// Create instance of MediaControlInputElement to run tests on.
media_controls_ =
static_cast<MediaControlsImpl*>(media_element_->GetMediaControls());
ASSERT_NE(media_controls_, nullptr);
loading_element_ =
MakeGarbageCollected<MediaControlLoadingPanelElement>(*media_controls_);
}
protected:
void ExpectStateIsHidden() {
EXPECT_EQ(MediaControlLoadingPanelElement::kHidden,
loading_element_->state_);
CheckIsHidden();
}
void ExpectStateIsPlaying() {
EXPECT_EQ(MediaControlLoadingPanelElement::kPlaying,
loading_element_->state_);
CheckIsShown();
}
void ExpectStateIsCoolingDown() {
EXPECT_EQ(MediaControlLoadingPanelElement::kCoolingDown,
loading_element_->state_);
CheckIsShown();
}
void SimulateLoadingMetadata() {
SetMediaElementState(HTMLMediaElement::kHaveNothing,
HTMLMediaElement::kNetworkLoading);
EXPECT_EQ(media_controls_->State(), MediaControlsImpl::kLoadingMetadata);
loading_element_->UpdateDisplayState();
}
void SimulateBuffering() {
SetMediaElementState(HTMLMediaElement::kHaveCurrentData,
HTMLMediaElement::kNetworkLoading, false);
EXPECT_EQ(media_controls_->State(), MediaControlsImpl::kBuffering);
loading_element_->UpdateDisplayState();
}
void SimulateStopped() {
SetMediaElementState(HTMLMediaElement::kHaveCurrentData,
HTMLMediaElement::kNetworkIdle);
EXPECT_EQ(media_controls_->State(), MediaControlsImpl::kStopped);
loading_element_->UpdateDisplayState();
}
void SimulatePlaying() {
SetMediaElementState(HTMLMediaElement::kHaveCurrentData,
HTMLMediaElement::kNetworkIdle, false);
EXPECT_EQ(media_controls_->State(), MediaControlsImpl::kPlaying);
loading_element_->UpdateDisplayState();
}
void SimulateNoSource() {
SetMediaElementState(HTMLMediaElement::kHaveNothing,
HTMLMediaElement::kNetworkNoSource);
EXPECT_EQ(media_controls_->State(), MediaControlsImpl::kNoSource);
loading_element_->UpdateDisplayState();
}
void SimulateAnimationIterations(int count) {
for (int i = 0; i < count; i++) {
TriggerEvent(event_type_names::kAnimationiteration);
}
}
void ExpectAnimationIterationCount(const String& value) {
ExpectAnimationIterationCount(loading_element_->mask1_background_, value);
ExpectAnimationIterationCount(loading_element_->mask2_background_, value);
}
void ExpectAnimationIterationInfinite() {
ExpectAnimationIterationCount("infinite");
}
void SimulateAnimationEnd() { TriggerEvent(event_type_names::kAnimationend); }
void SimulateControlsHidden() { loading_element_->OnControlsHidden(); }
void SimulateControlsShown() { loading_element_->OnControlsShown(); }
void RunPlayingTestCycle() {
ExpectStateIsHidden();
// Show the panel when we are loading metadata.
SimulateLoadingMetadata();
ExpectStateIsPlaying();
// Simulate some animations.
SimulateAnimationIterations(3);
ExpectAnimationIterationInfinite();
// Transition the media controls to a playing state and expect the loading
// panel to hide immediately.
SimulatePlaying();
// Make sure the loading panel is hidden now.
ExpectStateIsHidden();
// Show the panel when we are buffering.
SimulateBuffering();
ExpectStateIsPlaying();
// Simulate some animations.
SimulateAnimationIterations(3);
ExpectAnimationIterationInfinite();
// Transition the media controls to a playing state and expect the loading
// panel to hide immediately.
SimulatePlaying();
// Make sure the loading panel is hidden now.
ExpectStateIsHidden();
}
private:
void SetMediaElementState(HTMLMediaElement::ReadyState ready_state,
HTMLMediaElement::NetworkState network_state,
bool paused = true) {
media_element_->ready_state_ = ready_state;
media_element_->network_state_ = network_state;
media_element_->paused_ = paused;
}
void CheckIsHidden() {
EXPECT_FALSE(loading_element_->IsWanted());
EXPECT_FALSE(loading_element_->GetShadowRoot()->HasChildren());
}
void CheckIsShown() {
EXPECT_TRUE(loading_element_->IsWanted());
EXPECT_TRUE(loading_element_->GetShadowRoot()->HasChildren());
}
void ExpectAnimationIterationCount(Element* element, const String& value) {
EXPECT_EQ(value,
element->style()->getPropertyValue("animation-iteration-count"));
}
void TriggerEvent(const AtomicString& name) {
Event* event = Event::Create(name);
loading_element_->mask1_background_->DispatchEvent(*event);
}
Persistent<HTMLMediaElement> media_element_;
Persistent<MediaControlsImpl> media_controls_;
Persistent<MediaControlLoadingPanelElement> loading_element_;
};
TEST_F(MediaControlLoadingPanelElementTest, StateTransitions_ToPlaying) {
RunPlayingTestCycle();
}
TEST_F(MediaControlLoadingPanelElementTest, StateTransitions_ToStopped) {
ExpectStateIsHidden();
// Show the panel when we are loading metadata.
SimulateLoadingMetadata();
ExpectStateIsPlaying();
// Simulate some animations.
SimulateAnimationIterations(5);
ExpectAnimationIterationInfinite();
// Transition the media controls to a stopped state and expect the loading
// panel to start cooling down.
SimulateStopped();
ExpectStateIsCoolingDown();
ExpectAnimationIterationCount("6");
// Simulate the animations ending.
SimulateAnimationEnd();
// Make sure the loading panel is hidden now.
ExpectStateIsHidden();
}
TEST_F(MediaControlLoadingPanelElementTest, Reset_AfterComplete) {
RunPlayingTestCycle();
// Reset to kNoSource.
SimulateNoSource();
RunPlayingTestCycle();
}
TEST_F(MediaControlLoadingPanelElementTest, Reset_DuringCycle) {
ExpectStateIsHidden();
// Show the panel when we are loading metadata.
SimulateLoadingMetadata();
ExpectStateIsPlaying();
// Reset to kNoSource.
SimulateNoSource();
ExpectStateIsCoolingDown();
// Start loading metadata again before we have hidden.
SimulateLoadingMetadata();
SimulateAnimationEnd();
// We should now be showing the controls again.
ExpectStateIsPlaying();
ExpectAnimationIterationInfinite();
// Now move to playing.
SimulatePlaying();
ExpectStateIsHidden();
}
TEST_F(MediaControlLoadingPanelElementTest, SkipLoadingMetadata) {
ExpectStateIsHidden();
SimulatePlaying();
ExpectStateIsHidden();
}
TEST_F(MediaControlLoadingPanelElementTest, AnimationHiddenWhenControlsHidden) {
// Animation doesn't start when Media Controls are already hidden.
SimulateControlsHidden();
SimulateLoadingMetadata();
ExpectStateIsHidden();
// Animation appears once Media Controls are shown.
SimulateControlsShown();
ExpectStateIsPlaying();
// Animation is hidden when Media Controls are hidden again.
SimulateControlsHidden();
ExpectStateIsHidden();
}
} // namespace blink