Skip to content

Commit

Permalink
CrOS GMC V2: Add unit tests for LockScreenMediaView
Browse files Browse the repository at this point in the history
Bug: 1448702
Change-Id: I7df704f390359157baa42a76cfa0e433c85b7294
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4794845
Reviewed-by: Tommy Steimel <steimel@chromium.org>
Reviewed-by: Elie Maamari <emaamari@google.com>
Commit-Queue: Yiren Wang <yrw@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1187952}
  • Loading branch information
Yiren Wang authored and Chromium LUCI CQ committed Aug 24, 2023
1 parent d741f71 commit 7da52b8
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 17 deletions.
4 changes: 4 additions & 0 deletions ash/login/ui/lock_contents_view_test_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ LockScreenMediaControlsView* LockContentsViewTestApi::media_controls_view()
return view_->media_controls_view_;
}

LockScreenMediaView* LockContentsViewTestApi::media_view() const {
return view_->media_view_;
}

views::View* LockContentsViewTestApi::note_action() const {
return view_->note_action_;
}
Expand Down
1 change: 1 addition & 0 deletions ash/login/ui/lock_contents_view_test_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ASH_EXPORT LockContentsViewTestApi {
AccountId focused_user() const;
ScrollableUsersListView* users_list() const;
LockScreenMediaControlsView* media_controls_view() const;
LockScreenMediaView* media_view() const;
views::View* note_action() const;
views::View* tooltip_bubble() const;
views::View* management_bubble() const;
Expand Down
54 changes: 38 additions & 16 deletions ash/login/ui/lock_screen_media_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,23 @@ LockScreenMediaView::LockScreenMediaView(
// Media controls have not been dismissed initially.
Shell::Get()->media_controller()->SetMediaControlsDismissed(false);

SetLayoutManager(std::make_unique<views::FillLayout>());
const auto media_color_theme = GetCrosMediaColorTheme();

auto dismiss_button = std::make_unique<DismissButton>(
base::BindRepeating(&LockScreenMediaView::Hide, base::Unretained(this)),
media_color_theme.primary_foreground_color_id,
media_color_theme.secondary_foreground_color_id,
media_color_theme.focus_ring_color_id);
dismiss_button_ = dismiss_button.get();

view_ = AddChildView(
std::make_unique<global_media_controls::MediaNotificationViewAshImpl>(
this, /*item=*/nullptr, /*footer_view=*/nullptr,
/*device_selector_view=*/nullptr, std::move(dismiss_button),
media_color_theme,
global_media_controls::MediaDisplayPage::kLockScreenMediaView));

// |service| can be null in tests.
media_session::MediaSessionService* service =
Shell::Get()->shell_delegate()->GetMediaSessionService();
Expand All @@ -109,22 +126,6 @@ LockScreenMediaView::LockScreenMediaView(
global_media_controls::kMediaItemArtworkMinSize,
global_media_controls::kMediaItemArtworkDesiredSize,
artwork_observer_receiver_.BindNewPipeAndPassRemote());

SetLayoutManager(std::make_unique<views::FillLayout>());
const auto media_color_theme = GetCrosMediaColorTheme();

auto dismiss_button = std::make_unique<DismissButton>(
base::BindRepeating(&LockScreenMediaView::Hide, base::Unretained(this)),
media_color_theme.primary_foreground_color_id,
media_color_theme.secondary_foreground_color_id,
media_color_theme.focus_ring_color_id);

view_ = AddChildView(
std::make_unique<global_media_controls::MediaNotificationViewAshImpl>(
this, /*item=*/nullptr, /*footer_view=*/nullptr,
/*device_selector_view=*/nullptr, std::move(dismiss_button),
media_color_theme,
global_media_controls::MediaDisplayPage::kLockScreenMediaView));
}

LockScreenMediaView::~LockScreenMediaView() {
Expand Down Expand Up @@ -271,6 +272,27 @@ void LockScreenMediaView::OnSuspend() {
Hide();
}

///////////////////////////////////////////////////////////////////////////////
// Helper functions for testing:

void LockScreenMediaView::FlushForTesting() {
media_controller_remote_.FlushForTesting(); // IN-TEST
}

void LockScreenMediaView::SetMediaControllerForTesting(
mojo::Remote<media_session::mojom::MediaController> media_controller) {
media_controller_remote_ = std::move(media_controller);
}

views::Button* LockScreenMediaView::GetDismissButtonForTesting() {
return dismiss_button_;
}

global_media_controls::MediaNotificationViewAshImpl*
LockScreenMediaView::GetMediaNotificationViewForTesting() {
return view_;
}

///////////////////////////////////////////////////////////////////////////////
// LockScreenMediaView implementations:

Expand Down
16 changes: 16 additions & 0 deletions ash/login/ui/lock_screen_media_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

namespace ash {

namespace {
class DismissButton;
}

// View for media controls that appear on the lock screen if it is enabled. This
// replaces the old LockScreenMediaControlsView if the flag
// media::kGlobalMediaControlsCrOSUpdatedUI is enabled. It registers for media
Expand Down Expand Up @@ -84,6 +88,17 @@ class ASH_EXPORT LockScreenMediaView
// base::PowerSuspendObserver:
void OnSuspend() override;

// Helper functions for testing:
void FlushForTesting();

void SetMediaControllerForTesting(
mojo::Remote<media_session::mojom::MediaController> media_controller);

views::Button* GetDismissButtonForTesting();

global_media_controls::MediaNotificationViewAshImpl*
GetMediaNotificationViewForTesting();

private:
friend class LockScreenMediaViewTest;

Expand Down Expand Up @@ -118,6 +133,7 @@ class ASH_EXPORT LockScreenMediaView
const base::RepeatingClosure show_media_view_callback_;
const base::RepeatingClosure hide_media_view_callback_;

raw_ptr<DismissButton> dismiss_button_;
raw_ptr<global_media_controls::MediaNotificationViewAshImpl> view_;

base::WeakPtrFactory<LockScreenMediaView> weak_ptr_factory_{this};
Expand Down
186 changes: 185 additions & 1 deletion ash/login/ui/lock_screen_media_view_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,188 @@

#include "ash/login/ui/lock_screen_media_view.h"

// TODO(crbug.com/1448702): add tests.
#include "ash/login/ui/fake_login_detachable_base_model.h"
#include "ash/login/ui/lock_contents_view.h"
#include "ash/login/ui/lock_contents_view_test_api.h"
#include "ash/login/ui/login_test_base.h"
#include "base/test/power_monitor_test.h"
#include "base/test/scoped_feature_list.h"
#include "media/base/media_switches.h"
#include "services/media_session/public/cpp/test/test_media_controller.h"
#include "ui/events/base_event_utils.h"
#include "ui/views/test/button_test_api.h"

namespace ash {

using media_session::mojom::MediaSessionAction;
using media_session::test::TestMediaController;

class LockScreenMediaViewTest : public LoginTestBase {
public:
LockScreenMediaViewTest() = default;
LockScreenMediaViewTest(const LockScreenMediaViewTest&) = delete;
LockScreenMediaViewTest& operator=(const LockScreenMediaViewTest&) = delete;
~LockScreenMediaViewTest() override = default;

void SetUp() override {
feature_list_.InitAndEnableFeature(
media::kGlobalMediaControlsCrOSUpdatedUI);

set_start_session(true);
LoginTestBase::SetUp();

LockContentsView* lock_contents_view = new LockContentsView(
mojom::TrayActionState::kAvailable, LockScreen::ScreenType::kLock,
DataDispatcher(),
std::make_unique<FakeLoginDetachableBaseModel>(DataDispatcher()));
LockContentsViewTestApi lock_contents(lock_contents_view);
SetWidget(CreateWidgetWithContent(lock_contents_view));
SetUserCount(1);
media_view_ = lock_contents.media_view();

media_controller_ = std::make_unique<TestMediaController>();
media_view_->SetMediaControllerForTesting(
media_controller_->CreateMediaControllerRemote());
}

void TearDown() override {
media_view_ = nullptr;
LoginTestBase::TearDown();
}

void SimulateMediaSessionChanged(
media_session::mojom::MediaPlaybackState playback_state =
media_session::mojom::MediaPlaybackState::kPlaying) {
media_view_->MediaSessionChanged(base::UnguessableToken::Create());

media_session::mojom::MediaSessionInfoPtr session_info(
media_session::mojom::MediaSessionInfo::New());
session_info->playback_state = playback_state;
session_info->is_controllable = true;
media_view_->MediaSessionInfoChanged(session_info.Clone());
}

LockScreenMediaView* media_view() { return media_view_; }

global_media_controls::MediaNotificationViewAshImpl*
media_notification_view() {
return media_view_->GetMediaNotificationViewForTesting();
}

bool IsActionButtonVisible(MediaSessionAction action) {
views::Button* button =
media_notification_view()->GetActionButtonForTesting(action);
return button && button->GetVisible();
}

void Suspend() { power_monitor_source_.GenerateSuspendEvent(); }

TestMediaController* media_controller() const {
return media_controller_.get();
}

private:
base::test::ScopedFeatureList feature_list_;
raw_ptr<LockScreenMediaView> media_view_ = nullptr;
base::test::ScopedPowerMonitorTestSource power_monitor_source_;
std::unique_ptr<TestMediaController> media_controller_;
};

TEST_F(LockScreenMediaViewTest, DoNotUpdateMetadataBetweenSessions) {
media_session::MediaMetadata metadata;
metadata.source_title = u"source title";
metadata.title = u"title";
metadata.artist = u"artist";
SimulateMediaSessionChanged();
media_view()->MediaSessionMetadataChanged(metadata);

metadata.source_title = u"source title2";
metadata.title = u"title2";
metadata.artist = u"artist2";
SimulateMediaSessionChanged();
media_view()->MediaSessionMetadataChanged(metadata);

EXPECT_EQ(u"source title",
media_notification_view()->GetSourceLabelForTesting()->GetText());
EXPECT_EQ(u"title",
media_notification_view()->GetTitleLabelForTesting()->GetText());
EXPECT_EQ(u"artist",
media_notification_view()->GetArtistLabelForTesting()->GetText());
}

TEST_F(LockScreenMediaViewTest, DoNotUpdateActionsBetweenSessions) {
std::set<MediaSessionAction> actions;
actions.insert(MediaSessionAction::kPlay);
actions.insert(MediaSessionAction::kPause);
actions.insert(MediaSessionAction::kEnterPictureInPicture);
actions.insert(MediaSessionAction::kExitPictureInPicture);
SimulateMediaSessionChanged();
media_view()->MediaSessionActionsChanged(
std::vector<MediaSessionAction>(actions.begin(), actions.end()));

EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPause));
EXPECT_FALSE(
IsActionButtonVisible(MediaSessionAction::kEnterPictureInPicture));
EXPECT_FALSE(
IsActionButtonVisible(MediaSessionAction::kExitPictureInPicture));
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack));

actions.insert(MediaSessionAction::kPreviousTrack);
SimulateMediaSessionChanged();
media_view()->MediaSessionActionsChanged(
std::vector<MediaSessionAction>(actions.begin(), actions.end()));
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack));
}

TEST_F(LockScreenMediaViewTest, DoNotUpdatePositionBetweenSessions) {
media_session::MediaPosition media_position(
/*playback_rate=*/1, /*duration=*/base::Seconds(600),
/*position=*/base::Seconds(300), /*end_of_media=*/false);
SimulateMediaSessionChanged();
media_view()->MediaSessionPositionChanged(media_position);

media_session::MediaPosition media_position_paused(
/*playback_rate=*/0, /*duration=*/base::Seconds(600),
/*position=*/base::Seconds(300), /*end_of_media=*/false);
SimulateMediaSessionChanged();
media_view()->MediaSessionPositionChanged(media_position_paused);
EXPECT_EQ(media_position.playback_rate(),
media_notification_view()->GetPositionForTesting().playback_rate());
}

TEST_F(LockScreenMediaViewTest, DoNotUpdateArtworkBetweenSessions) {
SimulateMediaSessionChanged();

SkBitmap image;
image.allocN32Pixels(10, 10);
image.eraseColor(SK_ColorGREEN);
SimulateMediaSessionChanged();
media_view()->MediaControllerImageChanged(
media_session::mojom::MediaSessionImageType::kArtwork, image);

EXPECT_TRUE(media_notification_view()
->GetArtworkViewForTesting()
->GetImage()
.isNull());
}

TEST_F(LockScreenMediaViewTest, DismissButtonCheck) {
SimulateMediaSessionChanged();
EXPECT_TRUE(media_view()->GetVisible());

views::test::ButtonTestApi(media_view()->GetDismissButtonForTesting())
.NotifyClick(ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(),
gfx::Point(), ui::EventTimeForNow(), 0, 0));
media_view()->FlushForTesting();
EXPECT_EQ(1, media_controller()->stop_count());
EXPECT_FALSE(media_view()->GetVisible());
}

TEST_F(LockScreenMediaViewTest, PowerSuspendState) {
SimulateMediaSessionChanged();
EXPECT_TRUE(media_view()->GetVisible());
Suspend();
EXPECT_FALSE(media_view()->GetVisible());
}

} // namespace ash
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,11 @@ views::Button* MediaNotificationViewAshImpl::GetActionButtonForTesting(
return (i == action_buttons_.end()) ? nullptr : *i;
}

media_session::MediaPosition
MediaNotificationViewAshImpl::GetPositionForTesting() {
return position_;
}

views::Button* MediaNotificationViewAshImpl::GetStartCastingButtonForTesting() {
return start_casting_button_;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class COMPONENT_EXPORT(GLOBAL_MEDIA_CONTROLS) MediaNotificationViewAshImpl
views::ImageView* GetChevronIconForTesting();
views::Button* GetActionButtonForTesting(
media_session::mojom::MediaSessionAction action);
media_session::MediaPosition GetPositionForTesting();
views::Button* GetStartCastingButtonForTesting();
MediaItemUIFooter* GetFooterForTesting();
MediaItemUIDeviceSelector* GetDeviceSelectorForTesting();
Expand Down

0 comments on commit 7da52b8

Please sign in to comment.