#include "ash/game_dashboard/game_dashboard_context.h"
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "ash/accelerators/accelerator_commands.h"
#include "ash/accelerators/accelerator_controller_impl.h"
#include "ash/capture_mode/capture_mode_controller.h"
#include "ash/capture_mode/capture_mode_test_util.h"
#include "ash/capture_mode/capture_mode_types.h"
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/frame/frame_view_ash.h"
#include "ash/game_dashboard/game_dashboard_battery_view.h"
#include "ash/game_dashboard/game_dashboard_button.h"
#include "ash/game_dashboard/game_dashboard_constants.h"
#include "ash/game_dashboard/game_dashboard_context_test_api.h"
#include "ash/game_dashboard/game_dashboard_controller.h"
#include "ash/game_dashboard/game_dashboard_main_menu_view.h"
#include "ash/game_dashboard/game_dashboard_metrics.h"
#include "ash/game_dashboard/game_dashboard_network_view.h"
#include "ash/game_dashboard/game_dashboard_test_base.h"
#include "ash/game_dashboard/game_dashboard_toolbar_view.h"
#include "ash/game_dashboard/game_dashboard_utils.h"
#include "ash/game_dashboard/test_game_dashboard_delegate.h"
#include "ash/public/cpp/arc_game_controls_flag.h"
#include "ash/public/cpp/capture_mode/capture_mode_test_api.h"
#include "ash/public/cpp/style/dark_light_mode_controller.h"
#include "ash/public/cpp/tablet_mode.h"
#include "ash/public/cpp/test/shell_test_api.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/color_palette_controller.h"
#include "ash/style/dark_light_mode_controller_impl.h"
#include "ash/style/icon_button.h"
#include "ash/style/pill_button.h"
#include "ash/style/switch.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/power/battery_saver_controller.h"
#include "ash/system/power/power_status.h"
#include "ash/system/time/time_view.h"
#include "ash/system/toast/anchored_nudge_manager_impl.h"
#include "ash/system/toast/toast_manager_impl.h"
#include "ash/system/unified/feature_tile.h"
#include "ash/test/test_widget_delegates.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_observer.h"
#include "ash/wm/snap_group/snap_group_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_state_util.h"
#include "base/i18n/time_formatting.h"
#include "base/notreached.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h"
#include "chromeos/dbus/power/fake_power_manager_client.h"
#include "chromeos/services/network_config/public/cpp/fake_cros_network_config.h"
#include "chromeos/services/network_config/public/mojom/network_types.mojom-shared.h"
#include "chromeos/ui/base/app_types.h"
#include "chromeos/ui/base/window_properties.h"
#include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
#include "chromeos/ui/frame/frame_header.h"
#include "chromeos/ui/wm/window_util.h"
#include "components/ukm/test_ukm_recorder.h"
#include "extensions/common/constants.h"
#include "mojo/public/cpp/bindings/clone_traits.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/mojom/window_show_state.mojom-forward.h"
#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
#include "ui/events/keycodes/keyboard_codes_posix.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/scoped_animation_duration_scale_mode.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/animation/ink_drop.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/test/test_widget_builder.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/window_util.h"
namespace ash {
namespace {
const std::u16string& hidden_label = u"Hidden";
const std::u16string& visible_label = u"Visible";
constexpr base::TimeDelta kTouchDragDuration = base::Milliseconds(200);
const int kTouchDragSteps = 5;
enum class Movement { kTouch, kMouse };
template <typename T>
void VerifyHistogramValues(const base::HistogramTester& histograms,
const std::string& histogram_name,
const std::map<T, int>& histogram_values) {
for (const auto& entry : histogram_values) {
histograms.ExpectBucketCount(histogram_name, entry.first, entry.second);
}
}
void VerifyToggleMainMenuLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
const std::vector<int64_t>& expect_event_values) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries = ukm_recorder.GetEntriesByName(
BuildGameDashboardUkmEventName(kGameDashboardToggleMainMenuHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
EXPECT_EQ(2u, expect_event_values.size());
const size_t last_index = expect_entry_size - 1;
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[last_index],
ukm::builders::GameDashboard_ToggleMainMenu::kToggleOnName,
expect_event_values[0]);
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[last_index],
ukm::builders::GameDashboard_ToggleMainMenu::kToggleMethodName,
expect_event_values[1]);
}
void VerifyToolbarToggleStateLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
int64_t expect_event_value) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries =
ukm_recorder.GetEntriesByName(BuildGameDashboardUkmEventName(
kGameDashboardToolbarToggleStateHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1],
ukm::builders::GameDashboard_ToolbarToggleState::kToggleOnName,
expect_event_value);
}
void VerifyRecordingStartSourceLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
int64_t expect_event_value) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries =
ukm_recorder.GetEntriesByName(BuildGameDashboardUkmEventName(
kGameDashboardRecordingStartSourceHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1],
ukm::builders::GameDashboard_RecordingStartSource::kSourceName,
expect_event_value);
}
void VerifyScreenshotTakeSourceLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
int64_t expect_event_value) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries =
ukm_recorder.GetEntriesByName(BuildGameDashboardUkmEventName(
kGameDashboardScreenshotTakeSourceHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1],
ukm::builders::GameDashboard_ScreenshotTakeSource::kSourceName,
expect_event_value);
}
void VerifyGameControlsEditControlsWithEmptyStateLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
int64_t expect_event_value) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries =
ukm_recorder.GetEntriesByName(BuildGameDashboardUkmEventName(
kGameDashboardEditControlsWithEmptyStateHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1],
ukm::builders::GameDashboard_EditControlsWithEmptyState::kEmptyName,
expect_event_value);
}
void VerifyToolbarClickToExpandStateLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
int64_t expect_event_value) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries =
ukm_recorder.GetEntriesByName(BuildGameDashboardUkmEventName(
kGameDashboardToolbarClickToExpandStateHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1],
ukm::builders::GameDashboard_ToolbarClickToExpandState::kExpandedName,
expect_event_value);
}
void VerifyToolbarNewLocationLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
int64_t expect_event_value) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries =
ukm_recorder.GetEntriesByName(BuildGameDashboardUkmEventName(
kGameDashboardToolbarNewLocationHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1],
ukm::builders::GameDashboard_ToolbarNewLocation::kLocationName,
expect_event_value);
}
void VerifyFunctionTriggeredLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
int64_t expect_event_value) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries = ukm_recorder.GetEntriesByName(
BuildGameDashboardUkmEventName(kGameDashboardFunctionTriggeredHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1],
ukm::builders::GameDashboard_FunctionTriggered::kFunctionName,
expect_event_value);
}
void VerifyWelcomeDialogNotificationToggleStateLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
int64_t expect_event_value) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries =
ukm_recorder.GetEntriesByName(BuildGameDashboardUkmEventName(
kGameDashboardWelcomeDialogNotificationToggleStateHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1],
ukm::builders::GameDashboard_WelcomeDialogNotificationToggleState::
kToggleOnName,
expect_event_value);
}
void VerifyGameControlsHintToggleSourceLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
std::map<std::string, int64_t> expect_event_values) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries =
ukm_recorder.GetEntriesByName(BuildGameDashboardUkmEventName(
kGameDashboardControlsHintToggleSourceHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
for (const auto& value_entry : expect_event_values) {
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1], value_entry.first,
value_entry.second);
}
}
void VerifyGameControlsFeatureToggleStateLastUkmEvent(
const ukm::TestAutoSetUkmRecorder& ukm_recorder,
size_t expect_entry_size,
int64_t expect_event_value) {
EXPECT_GE(expect_entry_size, 1u);
const auto ukm_entries =
ukm_recorder.GetEntriesByName(BuildGameDashboardUkmEventName(
kGameDashboardControlsFeatureToggleStateHistogram));
EXPECT_EQ(expect_entry_size, ukm_entries.size());
ukm::TestAutoSetUkmRecorder::ExpectEntryMetric(
ukm_entries[expect_entry_size - 1],
ukm::builders::GameDashboard_ControlsFeatureToggleState::kToggleOnName,
expect_event_value);
}
class EventCapturer : public ui::EventHandler {
public:
EventCapturer() = default;
EventCapturer(const EventCapturer&) = delete;
EventCapturer& operator=(const EventCapturer&) = delete;
~EventCapturer() override {}
void Reset() { last_mouse_event_.reset(); }
ui::MouseEvent* last_mouse_event() { return last_mouse_event_.get(); }
private:
void OnMouseEvent(ui::MouseEvent* event) override {
last_mouse_event_ = std::make_unique<ui::MouseEvent>(*event);
}
std::unique_ptr<ui::MouseEvent> last_mouse_event_;
};
class NonResizableButtonModel : public chromeos::CaptionButtonModel {
public:
NonResizableButtonModel() = default;
NonResizableButtonModel(const NonResizableButtonModel&) = delete;
NonResizableButtonModel& operator=(const NonResizableButtonModel&) = delete;
~NonResizableButtonModel() override = default;
bool IsVisible(views::CaptionButtonIcon type) const override {
if (type == views::CAPTION_BUTTON_ICON_MINIMIZE) {
return true;
}
return false;
}
bool IsEnabled(views::CaptionButtonIcon type) const override { return true; }
bool InZoomMode() const override { return false; }
};
}
class GameDashboardContextTest : public GameDashboardTestBase {
public:
GameDashboardContextTest() = default;
GameDashboardContextTest(const GameDashboardContextTest&) = delete;
GameDashboardContextTest& operator=(const GameDashboardContextTest&) = delete;
~GameDashboardContextTest() override = default;
void SetUp() override {
GameDashboardTestBase::SetUp();
game_dashboard_utils::SetShowWelcomeDialog(false);
game_dashboard_utils::SetShowToolbar(false);
GetContext()->AddPostTargetHandler(&post_target_event_capturer_);
cros_network_ =
std::make_unique<chromeos::network_config::FakeCrosNetworkConfig>();
}
void TearDown() override {
GetContext()->RemovePostTargetHandler(&post_target_event_capturer_);
CloseGameWindow();
GameDashboardTestBase::TearDown();
}
void CloseGameWindow() {
game_window_.reset();
test_api_.reset();
frame_header_height_ = 0;
}
const gfx::Rect app_bounds() const { return app_bounds_; }
void SetAppBounds(gfx::Rect app_bounds) {
CHECK(!game_window_)
<< "App bounds cannot be changed after creating window. To set the app "
"bounds, call CloseWindow() and re-call this function.";
app_bounds_ = app_bounds;
}
int GetToolbarHeight() {
auto* widget = test_api_->GetToolbarWidget();
CHECK(widget) << "The toolbar must be opened first before trying to "
"retrieve its height.";
return widget->GetNativeWindow()->GetBoundsInScreen().height();
}
void ClickOnStartRecordingButtonInCaptureModeBarView() {
PillButton* start_recording_button = GetStartRecordingButton();
ASSERT_TRUE(start_recording_button);
LeftClickOn(start_recording_button);
WaitForRecordingToStart();
EXPECT_TRUE(CaptureModeController::Get()->is_recording_in_progress());
}
void CreateGameWindow(bool is_arc_window,
bool set_arc_game_controls_flags_prop = true) {
ASSERT_FALSE(game_window_);
ASSERT_FALSE(test_api_);
game_window_ =
CreateAppWindow((is_arc_window ? TestGameDashboardDelegate::kGameAppId
: extension_misc::kGeForceNowAppId),
(is_arc_window ? chromeos::AppType::ARC_APP
: chromeos::AppType::NON_APP),
app_bounds());
auto* context = GameDashboardController::Get()->GetGameDashboardContext(
game_window_.get());
ASSERT_TRUE(context);
test_api_ = std::make_unique<GameDashboardContextTestApi>(
context, GetEventGenerator());
ASSERT_TRUE(test_api_);
frame_header_height_ =
game_dashboard_utils::GetFrameHeaderHeight(game_window_.get());
DCHECK_GT(frame_header_height_, 0);
EXPECT_NEAR(test_api_->GetGameDashboardButtonCornerRadius(),
frame_header_height_ / 2, 0.000001f);
if (is_arc_window && set_arc_game_controls_flags_prop) {
game_window_->SetProperty(kArcGameControlsFlagsKey,
ArcGameControlsFlag::kKnown);
}
auto* game_dashboard_button_widget =
test_api_->GetGameDashboardButton()->GetWidget();
CHECK(game_dashboard_button_widget);
ASSERT_TRUE(game_dashboard_button_widget->CanActivate());
if (game_dashboard_utils::ShouldShowWelcomeDialog() &&
game_dashboard_utils::ShouldEnableFeatures()) {
ASSERT_TRUE(test_api_->GetWelcomeDialogWidget());
} else {
ASSERT_FALSE(test_api_->GetWelcomeDialogWidget());
}
}
void OpenMenuCheckGameControlsUIState(
std::array<bool, 3> hint_tile_states,
std::array<bool, 2> details_row_states,
std::array<bool, 2> feature_switch_states,
bool setup_exists) {
test_api_->OpenTheMainMenu();
if (const auto* tile = test_api_->GetMainMenuGameControlsTile();
hint_tile_states[0]) {
ASSERT_TRUE(tile);
EXPECT_EQ(hint_tile_states[1], tile->GetEnabled());
EXPECT_EQ(hint_tile_states[2], tile->IsToggled());
} else {
EXPECT_FALSE(tile);
}
auto* details_row = test_api_->GetMainMenuGameControlsDetailsButton();
EXPECT_EQ(details_row_states[0], !!details_row);
if (details_row) {
EXPECT_EQ(details_row_states[1], details_row->GetEnabled());
}
if (const auto* switch_button =
test_api_->GetMainMenuGameControlsFeatureSwitch();
feature_switch_states[0]) {
ASSERT_TRUE(switch_button);
EXPECT_EQ(feature_switch_states[1], switch_button->GetIsOn());
} else {
EXPECT_FALSE(switch_button);
}
auto* setup_button = test_api_->GetMainMenuGameControlsSetupButton();
ASSERT_EQ(!!setup_button, setup_exists);
if (setup_button) {
EXPECT_EQ(details_row_states[1], setup_button->GetEnabled());
}
test_api_->OpenTheToolbar();
if (const auto* game_controls_button =
test_api_->GetToolbarGameControlsButton();
hint_tile_states[0]) {
ASSERT_TRUE(game_controls_button);
EXPECT_EQ(hint_tile_states[1], game_controls_button->GetEnabled());
EXPECT_EQ(hint_tile_states[2], game_controls_button->toggled());
} else {
EXPECT_FALSE(game_controls_button);
}
test_api_->CloseTheToolbar();
test_api_->CloseTheMainMenu();
}
gfx::Point DragToolbarPointForPosition(
GameDashboardToolbarSnapLocation expected_location) {
const auto window_bounds = game_window_->GetBoundsInScreen();
const auto window_center_point = window_bounds.CenterPoint();
const int x_offset = window_bounds.width() / 4;
const int y_offset = window_bounds.height() / 4;
switch (expected_location) {
case GameDashboardToolbarSnapLocation::kTopLeft:
return gfx::Point(window_center_point.x() - x_offset,
window_center_point.y() - y_offset);
case GameDashboardToolbarSnapLocation::kTopRight:
return gfx::Point(window_center_point.x() + x_offset,
window_center_point.y() - y_offset);
case GameDashboardToolbarSnapLocation::kBottomRight:
return gfx::Point(window_center_point.x() + x_offset,
window_center_point.y() + y_offset);
case ash::GameDashboardToolbarSnapLocation::kBottomLeft:
return gfx::Point(window_center_point.x() - x_offset,
window_center_point.y() + y_offset);
default:
NOTREACHED();
}
}
void VerifyToolbarDrag(Movement move_type) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kTopRight);
DragToolbarToPoint(move_type,
DragToolbarPointForPosition(
GameDashboardToolbarSnapLocation::kTopRight));
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kTopRight);
DragToolbarToPoint(move_type,
DragToolbarPointForPosition(
GameDashboardToolbarSnapLocation::kBottomRight));
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kBottomRight);
DragToolbarToPoint(move_type,
DragToolbarPointForPosition(
GameDashboardToolbarSnapLocation::kBottomLeft));
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kBottomLeft);
DragToolbarToPoint(move_type,
DragToolbarPointForPosition(
GameDashboardToolbarSnapLocation::kTopLeft));
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kTopLeft);
}
void VerifyGameDashboardButtonState(GameDashboardContextTestApi* test_api,
bool is_recording) {
EXPECT_EQ(is_recording, test_api->GetGameDashboardButton()->is_recording());
std::u16string expected_title;
if (is_recording) {
expected_title = l10n_util::GetStringFUTF16(
IDS_ASH_GAME_DASHBOARD_GAME_DASHBOARD_BUTTON_RECORDING,
test_api->GetRecordingDuration());
} else {
expected_title = l10n_util::GetStringUTF16(
IDS_ASH_GAME_DASHBOARD_GAME_DASHBOARD_BUTTON_TITLE);
}
EXPECT_EQ(expected_title,
test_api->GetGameDashboardButtonTitle()->GetText());
}
void VerifyGameDashboardButtonState(bool is_recording) {
VerifyGameDashboardButtonState(test_api_.get(), is_recording);
}
gfx::Point MoveCursorToEmptySpaceInFrameHeader(
GameDashboardContextTestApi* test_api) {
const auto window_bounds =
test_api->context()->game_window()->GetBoundsInScreen();
const auto gd_button_bounds_x =
test_api->GetGameDashboardButton()->GetBoundsInScreen().x();
gfx::Point new_mouse_location =
gfx::Point((window_bounds.x() + gd_button_bounds_x) / 2,
window_bounds.y() + frame_header_height_ / 2);
GetEventGenerator()->MoveMouseTo(new_mouse_location);
return new_mouse_location;
}
void RecordGameAndVerifyButtons(
GameDashboardContextTestApi* recording_window_test_api,
GameDashboardContextTestApi* other_window_test_api) {
auto* event_generator = GetEventGenerator();
for (auto* test_api : {recording_window_test_api, other_window_test_api}) {
MoveCursorToEmptySpaceInFrameHeader(test_api);
event_generator->ClickLeftButton();
test_api->OpenTheMainMenu();
const auto* record_game_tile = test_api->GetMainMenuRecordGameTile();
ASSERT_TRUE(record_game_tile);
EXPECT_TRUE(record_game_tile->GetEnabled());
EXPECT_FALSE(record_game_tile->IsToggled());
test_api->OpenTheToolbar();
const auto* record_game_button = test_api->GetToolbarRecordGameButton();
ASSERT_TRUE(record_game_button);
EXPECT_TRUE(record_game_button->GetEnabled());
EXPECT_FALSE(record_game_button->toggled());
}
const auto& recording_window_timer =
recording_window_test_api->GetRecordingTimer();
const auto& other_window_timer = other_window_test_api->GetRecordingTimer();
EXPECT_FALSE(recording_window_timer.IsRunning());
EXPECT_FALSE(other_window_timer.IsRunning());
VerifyGameDashboardButtonState(recording_window_test_api,
false);
VerifyGameDashboardButtonState(other_window_test_api,
false);
auto* recording_window =
recording_window_test_api->context()->game_window();
ASSERT_TRUE(recording_window);
MoveCursorToEmptySpaceInFrameHeader(recording_window_test_api);
event_generator->ClickLeftButton();
recording_window_test_api->OpenTheMainMenu();
LeftClickOn(recording_window_test_api->GetMainMenuRecordGameTile());
base::RunLoop().RunUntilIdle();
ClickOnStartRecordingButtonInCaptureModeBarView();
recording_window_test_api->OpenTheMainMenu();
EXPECT_TRUE(recording_window_timer.IsRunning());
EXPECT_FALSE(other_window_timer.IsRunning());
VerifyGameDashboardButtonState(recording_window_test_api,
true);
VerifyGameDashboardButtonState(other_window_test_api,
false);
VerifyRecordGameStatus(
recording_window_test_api->GetMainMenuRecordGameTile(),
recording_window_test_api->GetToolbarRecordGameButton(),
true, true);
MoveCursorToEmptySpaceInFrameHeader(other_window_test_api);
event_generator->ClickLeftButton();
other_window_test_api->OpenTheMainMenu();
VerifyRecordGameStatus(other_window_test_api->GetMainMenuRecordGameTile(),
other_window_test_api->GetToolbarRecordGameButton(),
false, false);
MoveCursorToEmptySpaceInFrameHeader(recording_window_test_api);
event_generator->ClickLeftButton();
recording_window_test_api->OpenTheMainMenu();
LeftClickOn(recording_window_test_api->GetMainMenuRecordGameTile());
EXPECT_FALSE(CaptureModeController::Get()->is_recording_in_progress());
WaitForCaptureFileToBeSaved();
VerifyRecordGameStatus(
recording_window_test_api->GetMainMenuRecordGameTile(),
recording_window_test_api->GetToolbarRecordGameButton(),
true, false);
MoveCursorToEmptySpaceInFrameHeader(other_window_test_api);
event_generator->ClickLeftButton();
other_window_test_api->OpenTheMainMenu();
VerifyRecordGameStatus(other_window_test_api->GetMainMenuRecordGameTile(),
other_window_test_api->GetToolbarRecordGameButton(),
true, false);
EXPECT_FALSE(recording_window_timer.IsRunning());
EXPECT_FALSE(other_window_timer.IsRunning());
VerifyGameDashboardButtonState(recording_window_test_api,
false);
VerifyGameDashboardButtonState(other_window_test_api,
false);
other_window_test_api->CloseTheToolbar();
other_window_test_api->CloseTheMainMenu();
MoveCursorToEmptySpaceInFrameHeader(recording_window_test_api);
event_generator->ClickLeftButton();
recording_window_test_api->OpenTheMainMenu();
recording_window_test_api->CloseTheToolbar();
recording_window_test_api->CloseTheMainMenu();
}
void VerifyRecordGameStatus(FeatureTile* game_tile,
IconButton* game_button,
bool enabled,
bool toggled) {
ASSERT_TRUE(game_tile);
ASSERT_TRUE(game_button);
EXPECT_EQ(enabled, game_tile->GetEnabled());
EXPECT_EQ(enabled, game_button->GetEnabled());
EXPECT_EQ(toggled, game_tile->IsToggled());
EXPECT_EQ(toggled, game_button->toggled());
}
void TabNavigateForward() {
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_TAB, ui::EF_NONE);
}
void TabNavigateBackward() {
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN);
}
void PressKeyAndVerify(ui::KeyboardCode key,
GameDashboardToolbarSnapLocation desired_location) {
GetEventGenerator()->PressAndReleaseKey(key);
EXPECT_EQ(test_api_->GetToolbarSnapLocation(), desired_location);
}
void CreateAnArcAppAndToggleFullscreen(
std::unique_ptr<chromeos::CaptionButtonModel> caption_button_model =
nullptr) {
SetAppBounds(gfx::Rect(50, 50, 800, 700));
CreateGameWindow(true,
true);
auto* window_state = WindowState::Get(game_window_.get());
ASSERT_TRUE(window_state->IsNormalStateType());
views::Widget* button_widget = test_api_->GetGameDashboardButtonWidget();
CHECK(button_widget);
if (caption_button_model) {
auto* frame_view = FrameViewAsh::Get(game_window_.get());
ASSERT_TRUE(frame_view);
frame_view->SetCaptionButtonModel(std::move(caption_button_model));
}
ASSERT_FALSE(test_api_->GetGameDashboardButtonRevealController());
ToggleFullScreen(window_state, nullptr);
auto* frame_view = FrameViewAsh::Get(game_window_.get());
chromeos::FrameCaptionButtonContainerView::TestApi test_api(
frame_view->GetHeaderView()->caption_button_container());
test_api.EndAnimations();
ASSERT_TRUE(window_state->IsFullscreen());
ASSERT_FALSE(button_widget->IsVisible());
ASSERT_TRUE(test_api_->GetGameDashboardButtonRevealController());
}
protected:
void DragToolbarToPoint(Movement move_type,
const gfx::Point& new_location,
bool drop = true) {
const auto* widget = test_api_->GetToolbarWidget();
DCHECK(widget) << "Cannot drag toolbar because it's unavailable on screen.";
const auto toolbar_bounds = widget->GetNativeWindow()->GetBoundsInScreen();
auto* event_generator = GetEventGenerator();
event_generator->set_current_screen_location(toolbar_bounds.CenterPoint());
switch (move_type) {
case Movement::kMouse:
event_generator->PressLeftButton();
event_generator->MoveMouseTo(new_location);
if (drop) {
event_generator->ReleaseLeftButton();
}
break;
case Movement::kTouch:
event_generator->PressTouch();
event_generator->MoveTouchBy(50, 0);
event_generator->MoveTouch(new_location);
if (drop) {
event_generator->ReleaseTouch();
}
break;
}
base::RunLoop().RunUntilIdle();
}
void UpdatePowerStatus(double battery_percent,
base::TimeDelta time_to_empty) {
power_manager::PowerSupplyProperties props;
auto external_power =
power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED;
auto battery_state =
power_manager::PowerSupplyProperties_BatteryState_DISCHARGING;
props.set_battery_percent(battery_percent);
props.set_external_power(external_power);
props.set_battery_state(battery_state);
props.set_is_calculating_battery_time(false);
props.set_battery_time_to_empty_sec(time_to_empty.InSecondsF());
chromeos::FakePowerManagerClient::Get()->UpdatePowerProperties(props);
}
chromeos::network_config::FakeCrosNetworkConfig* cros_network() {
return cros_network_.get();
}
std::unique_ptr<aura::Window> game_window_;
std::unique_ptr<GameDashboardContextTestApi> test_api_;
int frame_header_height_ = 0;
EventCapturer post_target_event_capturer_;
private:
std::unique_ptr<chromeos::network_config::FakeCrosNetworkConfig>
cros_network_;
gfx::Rect app_bounds_ = gfx::Rect(50, 50, 800, 400);
};
TEST_F(GameDashboardContextTest, GameControlsMenuState) {
CreateGameWindow(true,
true);
OpenMenuCheckGameControlsUIState(
{true, false, false},
{true, false},
{false, false},
true);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(ArcGameControlsFlag::kKnown |
ArcGameControlsFlag::kAvailable));
OpenMenuCheckGameControlsUIState(
{true, false, false},
{true, true},
{true, false},
false);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEmpty | ArcGameControlsFlag::kEnabled));
OpenMenuCheckGameControlsUIState(
{true, false, false},
{true, true},
{false, false},
true);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(ArcGameControlsFlag::kKnown |
ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled));
OpenMenuCheckGameControlsUIState(
{true, true, false},
{true, true},
{true, true},
false);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kHint));
OpenMenuCheckGameControlsUIState(
{true, true, true},
{true, true},
{true, true},
false);
}
TEST_F(GameDashboardContextTest, GameControlsSetupNudge) {
CreateGameWindow(true);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEmpty | ArcGameControlsFlag::kEnabled));
test_api_->OpenTheMainMenu();
EXPECT_TRUE(test_api_->GetGameControlsSetupNudge());
task_environment()->FastForwardBy(
AnchoredNudgeManagerImpl::kNudgeMediumDuration);
EXPECT_FALSE(test_api_->GetGameControlsSetupNudge());
test_api_->CloseTheMainMenu();
test_api_->OpenTheMainMenu();
EXPECT_TRUE(test_api_->GetGameControlsSetupNudge());
LeftClickOn(test_api_->GetMainMenuSettingsButton());
EXPECT_FALSE(test_api_->GetGameControlsSetupNudge());
LeftClickOn(test_api_->GetSettingsViewBackButton());
EXPECT_TRUE(test_api_->GetGameControlsSetupNudge());
test_api_->CloseTheMainMenu();
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEmpty | ArcGameControlsFlag::kEnabled |
ArcGameControlsFlag::kO4C));
test_api_->OpenTheMainMenu();
EXPECT_FALSE(test_api_->GetGameControlsSetupNudge());
}
TEST_F(GameDashboardContextTest, GameControlsMenuFunctions) {
CreateGameWindow(true);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kHint));
EXPECT_FALSE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kMenu));
test_api_->OpenTheMainMenu();
EXPECT_TRUE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kMenu));
test_api_->OpenTheToolbar();
auto* detail_row = test_api_->GetMainMenuGameControlsDetailsButton();
auto* switch_button = test_api_->GetMainMenuGameControlsFeatureSwitch();
auto* game_controls_button = test_api_->GetToolbarGameControlsButton();
EXPECT_TRUE(detail_row->GetEnabled());
EXPECT_TRUE(switch_button->GetEnabled());
EXPECT_TRUE(switch_button->GetIsOn());
EXPECT_TRUE(game_controls_button->GetEnabled());
EXPECT_TRUE(game_controls_button->toggled());
LeftClickOn(switch_button);
EXPECT_TRUE(detail_row->GetEnabled());
EXPECT_TRUE(switch_button->GetEnabled());
EXPECT_FALSE(switch_button->GetIsOn());
EXPECT_FALSE(game_controls_button->GetEnabled());
EXPECT_FALSE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kHint));
LeftClickOn(detail_row);
EXPECT_FALSE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kEdit));
test_api_->CloseTheToolbar();
test_api_->CloseTheMainMenu();
EXPECT_FALSE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kMenu));
OpenMenuCheckGameControlsUIState(
{true, false, false},
{true, true},
{true, false},
false);
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
detail_row = test_api_->GetMainMenuGameControlsDetailsButton();
switch_button = test_api_->GetMainMenuGameControlsFeatureSwitch();
game_controls_button = test_api_->GetToolbarGameControlsButton();
const auto* game_controls_tile = test_api_->GetMainMenuGameControlsTile();
LeftClickOn(switch_button);
EXPECT_TRUE(detail_row->GetEnabled());
EXPECT_TRUE(switch_button->GetEnabled());
EXPECT_TRUE(switch_button->GetIsOn());
EXPECT_TRUE(game_controls_button->GetEnabled());
EXPECT_TRUE(game_controls_button->toggled());
EXPECT_TRUE(game_controls_tile->IsToggled());
LeftClickOn(game_controls_tile);
test_api_->CloseTheToolbar();
test_api_->CloseTheMainMenu();
OpenMenuCheckGameControlsUIState(
{true, true, false},
{true, true},
{true, true},
false);
}
TEST_F(GameDashboardContextTest, GameControlsEditMode) {
CreateGameWindow(true);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kHint));
auto* game_dashboard_button = test_api_->GetGameDashboardButton();
EXPECT_TRUE(game_dashboard_button->GetEnabled());
LeftClickOn(game_dashboard_button);
EXPECT_TRUE(test_api_->GetMainMenuWidget());
test_api_->OpenTheToolbar();
auto* tool_bar_widget = test_api_->GetToolbarWidget();
EXPECT_TRUE(tool_bar_widget);
EXPECT_TRUE(tool_bar_widget->IsVisible());
LeftClickOn(test_api_->GetMainMenuGameControlsDetailsButton());
EXPECT_TRUE(game_dashboard_utils::IsFlagSet(
game_window_->GetProperty(kArcGameControlsFlagsKey),
ArcGameControlsFlag::kEdit));
EXPECT_FALSE(test_api_->GetMainMenuWidget());
EXPECT_FALSE(tool_bar_widget->IsVisible());
EXPECT_FALSE(game_dashboard_button->GetEnabled());
LeftClickOn(game_dashboard_button);
EXPECT_FALSE(test_api_->GetMainMenuWidget());
ArcGameControlsFlag flags =
game_window_->GetProperty(kArcGameControlsFlagsKey);
flags = game_dashboard_utils::UpdateFlag(flags, ArcGameControlsFlag::kEdit,
false);
game_window_->SetProperty(kArcGameControlsFlagsKey, flags);
EXPECT_TRUE(game_dashboard_button->GetEnabled());
LeftClickOn(game_dashboard_button);
EXPECT_TRUE(test_api_->GetMainMenuWidget());
EXPECT_TRUE(tool_bar_widget->IsVisible());
}
TEST_F(GameDashboardContextTest, ZorderWithGameControls) {
CreateGameWindow(true);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kHint));
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
EXPECT_TRUE(test_api_->GetMainMenuWidget()->IsStackedAbove(
test_api_->GetToolbarWidget()->GetNativeView()));
LeftClickOn(test_api_->GetMainMenuGameControlsTile());
EXPECT_TRUE(test_api_->GetMainMenuWidget()->IsStackedAbove(
test_api_->GetToolbarWidget()->GetNativeView()));
LeftClickOn(test_api_->GetMainMenuGameControlsTile());
EXPECT_TRUE(test_api_->GetMainMenuWidget()->IsStackedAbove(
test_api_->GetToolbarWidget()->GetNativeView()));
LeftClickOn(test_api_->GetMainMenuGameControlsFeatureSwitch());
EXPECT_TRUE(test_api_->GetMainMenuWidget()->IsStackedAbove(
test_api_->GetToolbarWidget()->GetNativeView()));
LeftClickOn(test_api_->GetMainMenuGameControlsFeatureSwitch());
EXPECT_TRUE(test_api_->GetMainMenuWidget()->IsStackedAbove(
test_api_->GetToolbarWidget()->GetNativeView()));
}
TEST_F(GameDashboardContextTest,
RecordEditControlsWithEmptyStateHistogramTest) {
CreateGameWindow(true);
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kHint));
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuGameControlsDetailsButton());
const std::string histogram_name = BuildGameDashboardHistogramName(
kGameDashboardEditControlsWithEmptyStateHistogram);
std::map<bool, int> expected_histogram_values;
expected_histogram_values[false]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyGameControlsEditControlsWithEmptyStateLastUkmEvent(
ukm_recorder, 1u, 0);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kEmpty));
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuGameControlsDetailsButton());
expected_histogram_values[true]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyGameControlsEditControlsWithEmptyStateLastUkmEvent(
ukm_recorder, 2u, 1);
}
TEST_F(GameDashboardContextTest, RecordControlsHintToggleSourceHistogramTest) {
CreateGameWindow(true);
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
const std::string histogram_name_on =
BuildGameDashboardHistogramName(
kGameDashboardControlsHintToggleSourceHistogram)
.append(kGameDashboardHistogramSeparator)
.append(kGameDashboardHistogramOn);
const std::string histogram_name_off =
BuildGameDashboardHistogramName(
kGameDashboardControlsHintToggleSourceHistogram)
.append(kGameDashboardHistogramSeparator)
.append(kGameDashboardHistogramOff);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kHint));
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
LeftClickOn(test_api_->GetMainMenuGameControlsTile());
std::map<GameDashboardMenu, int> expected_off_histogram_values;
expected_off_histogram_values[GameDashboardMenu::kMainMenu]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
VerifyGameControlsHintToggleSourceLastUkmEvent(
ukm_recorder, 1u,
{{ukm::builders::GameDashboard_ControlsHintToggleSource::kToggleOnName,
static_cast<int64_t>(false)},
{ukm::builders::GameDashboard_ControlsHintToggleSource::kSourceName,
static_cast<int64_t>(GameDashboardMenu::kMainMenu)}});
LeftClickOn(test_api_->GetToolbarGameControlsButton());
std::map<GameDashboardMenu, int> expected_on_histogram_values;
expected_on_histogram_values[GameDashboardMenu::kToolbar]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
VerifyGameControlsHintToggleSourceLastUkmEvent(
ukm_recorder, 2u,
{{ukm::builders::GameDashboard_ControlsHintToggleSource::kToggleOnName,
static_cast<int64_t>(true)},
{ukm::builders::GameDashboard_ControlsHintToggleSource::kSourceName,
static_cast<int64_t>(GameDashboardMenu::kToolbar)}});
LeftClickOn(test_api_->GetToolbarGameControlsButton());
expected_off_histogram_values[GameDashboardMenu::kToolbar]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
VerifyGameControlsHintToggleSourceLastUkmEvent(
ukm_recorder, 3u,
{{ukm::builders::GameDashboard_ControlsHintToggleSource::kToggleOnName,
static_cast<int64_t>(false)},
{ukm::builders::GameDashboard_ControlsHintToggleSource::kSourceName,
static_cast<int64_t>(GameDashboardMenu::kToolbar)}});
base::RunLoop().RunUntilIdle();
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuGameControlsTile());
expected_on_histogram_values[GameDashboardMenu::kMainMenu]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
VerifyGameControlsHintToggleSourceLastUkmEvent(
ukm_recorder, 4u,
{{ukm::builders::GameDashboard_ControlsHintToggleSource::kToggleOnName,
static_cast<int64_t>(true)},
{ukm::builders::GameDashboard_ControlsHintToggleSource::kSourceName,
static_cast<int64_t>(GameDashboardMenu::kMainMenu)}});
}
TEST_F(GameDashboardContextTest,
RecordControlsFeatureToggleStateHistogramTest) {
CreateGameWindow(true);
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kHint));
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuGameControlsFeatureSwitch());
const std::string histogram_name = BuildGameDashboardHistogramName(
kGameDashboardControlsFeatureToggleStateHistogram);
std::map<bool, int> expected_histogram_values;
expected_histogram_values[false]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyGameControlsFeatureToggleStateLastUkmEvent(
ukm_recorder, 1u, static_cast<int64_t>(false));
LeftClickOn(test_api_->GetMainMenuGameControlsFeatureSwitch());
expected_histogram_values[true]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyGameControlsFeatureToggleStateLastUkmEvent(
ukm_recorder, 2u, static_cast<int64_t>(true));
}
TEST_F(GameDashboardContextTest, CompatModeArcGame) {
CreateGameWindow(true);
game_window_->SetProperty(kArcResizeLockTypeKey,
ArcResizeLockType::RESIZE_ENABLED_TOGGLABLE);
test_api_->OpenTheMainMenu();
const auto* screen_size_button =
test_api_->GetMainMenuScreenSizeSettingsButton();
ASSERT_TRUE(screen_size_button);
EXPECT_TRUE(screen_size_button->GetEnabled());
}
TEST_F(GameDashboardContextTest, ScreenSizeRowAvailability) {
CreateGameWindow(true);
game_window_->SetProperty(kArcResizeLockTypeKey, ArcResizeLockType::NONE);
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(ArcGameControlsFlag::kKnown |
ArcGameControlsFlag::kO4C));
test_api_->OpenTheMainMenu();
EXPECT_FALSE(test_api_->GetMainMenuScreenSizeSettingsButton());
}
TEST_F(GameDashboardContextTest, ScreenSizeRowSubtitle_PortraitResizable) {
SetAppBounds(gfx::Rect(50, 50, 400, 700));
CreateGameWindow(true);
game_window_->SetProperty(kArcResizeLockTypeKey,
ArcResizeLockType::RESIZE_DISABLED_TOGGLABLE);
test_api_->OpenTheMainMenu();
EXPECT_EQ(u"Portrait", test_api_->GetMainMenuScreenSizeSubtitle());
}
TEST_F(GameDashboardContextTest, ScreenSizeRowSubtitle_LandscapeResizable) {
CreateGameWindow(true);
game_window_->SetProperty(kArcResizeLockTypeKey,
ArcResizeLockType::RESIZE_DISABLED_TOGGLABLE);
test_api_->OpenTheMainMenu();
EXPECT_EQ(u"Landscape", test_api_->GetMainMenuScreenSizeSubtitle());
}
TEST_F(GameDashboardContextTest, ScreenSizeRowSubtitle_FreeformResizable) {
CreateGameWindow(true);
game_window_->SetProperty(kArcResizeLockTypeKey,
ArcResizeLockType::RESIZE_ENABLED_TOGGLABLE);
test_api_->OpenTheMainMenu();
EXPECT_EQ(u"Resizable", test_api_->GetMainMenuScreenSizeSubtitle());
}
TEST_F(GameDashboardContextTest, ScreenSizeRowSubtitle_PortraitNonTogglable) {
SetAppBounds(gfx::Rect(50, 50, 400, 700));
CreateGameWindow(true);
game_window_->SetProperty(kArcResizeLockTypeKey,
ArcResizeLockType::RESIZE_DISABLED_NONTOGGLABLE);
test_api_->OpenTheMainMenu();
EXPECT_EQ(u"Only portrait available",
test_api_->GetMainMenuScreenSizeSubtitle());
}
TEST_F(GameDashboardContextTest, ScreenSizeRowSubtitle_LandscapeNonTogglable) {
CreateGameWindow(true);
game_window_->SetProperty(kArcResizeLockTypeKey,
ArcResizeLockType::RESIZE_DISABLED_NONTOGGLABLE);
test_api_->OpenTheMainMenu();
EXPECT_EQ(u"Only landscape available",
test_api_->GetMainMenuScreenSizeSubtitle());
}
TEST_F(GameDashboardContextTest, ScreenSizeRowSubtitle_FullscreenTogglable) {
CreateAnArcAppAndToggleFullscreen();
AcceleratorControllerImpl* controller =
Shell::Get()->accelerator_controller();
const ui::Accelerator gd_accelerator(ui::VKEY_G, ui::EF_COMMAND_DOWN);
auto* button_widget = test_api_->GetGameDashboardButtonWidget();
CHECK(button_widget);
ASSERT_TRUE(controller->Process(gd_accelerator));
ASSERT_TRUE(button_widget->IsVisible());
EXPECT_EQ(u"Exit fullscreen to resize",
test_api_->GetMainMenuScreenSizeSubtitle());
}
TEST_F(GameDashboardContextTest, ScreenSizeRowSubtitle_FullscreenNonTogglable) {
CreateAnArcAppAndToggleFullscreen(
std::make_unique<NonResizableButtonModel>());
AcceleratorControllerImpl* controller =
Shell::Get()->accelerator_controller();
const ui::Accelerator gd_accelerator(ui::VKEY_G, ui::EF_COMMAND_DOWN);
auto* button_widget = test_api_->GetGameDashboardButtonWidget();
CHECK(button_widget);
ASSERT_TRUE(controller->Process(gd_accelerator));
ASSERT_TRUE(button_widget->IsVisible());
EXPECT_EQ(u"Only fullscreen available",
test_api_->GetMainMenuScreenSizeSubtitle());
}
TEST_F(GameDashboardContextTest, NonCompatModeArcGame) {
CreateGameWindow(true);
game_window_->SetProperty(kArcResizeLockTypeKey,
ArcResizeLockType::RESIZE_DISABLED_NONTOGGLABLE);
test_api_->OpenTheMainMenu();
const auto* screen_size_button =
test_api_->GetMainMenuScreenSizeSettingsButton();
ASSERT_TRUE(screen_size_button);
EXPECT_FALSE(screen_size_button->GetEnabled());
EXPECT_EQ(u"This app supports only this size.",
screen_size_button->GetTooltipText());
}
TEST_F(GameDashboardContextTest, SelectScreenSizeButton) {
CreateGameWindow(true);
game_window_->SetProperty(kArcResizeLockTypeKey,
ArcResizeLockType::RESIZE_DISABLED_TOGGLABLE);
test_api_->OpenTheMainMenu();
const auto* screen_size_button =
test_api_->GetMainMenuScreenSizeSettingsButton();
ASSERT_TRUE(screen_size_button);
ASSERT_TRUE(screen_size_button->GetEnabled());
LeftClickOn(screen_size_button);
EXPECT_FALSE(test_api_->GetMainMenuWidget());
}
TEST_F(GameDashboardContextTest, TwoGameWindowsRecordingState) {
CreateGameWindow(true);
auto gfn_game_window = CreateAppWindow(extension_misc::kGeForceNowAppId,
chromeos::AppType::NON_APP,
gfx::Rect(950, 550, 400, 200));
auto* gfn_game_context =
GameDashboardController::Get()->GetGameDashboardContext(
gfn_game_window.get());
ASSERT_TRUE(gfn_game_context);
auto gfn_window_test_api =
GameDashboardContextTestApi(gfn_game_context, GetEventGenerator());
RecordGameAndVerifyButtons(
test_api_.get(),
&gfn_window_test_api);
RecordGameAndVerifyButtons(
&gfn_window_test_api,
test_api_.get());
}
TEST_F(GameDashboardContextTest, MainMenuBatteryView) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature({features::kGameDashboardUtilities});
CreateGameWindow(true);
test_api_->OpenTheMainMenu();
auto* battery_view = test_api_->GetMainMenuBatteryView();
ASSERT_TRUE(battery_view);
ASSERT_TRUE(battery_view->GetVisible());
auto* dark_light_mode_controller = DarkLightModeControllerImpl::Get();
dark_light_mode_controller->SetDarkModeEnabledForTest(false);
const auto light_theme_image = battery_view->GetImageModel();
dark_light_mode_controller->SetDarkModeEnabledForTest(true);
const auto dark_theme_image = battery_view->GetImageModel();
ASSERT_NE(light_theme_image, dark_theme_image);
PowerStatus::Get()->SetBatterySaverStateForTesting(true);
UpdatePowerStatus(features::kBatterySaverActivationChargePercent.Get(),
base::Hours(8));
EXPECT_TRUE(PowerStatus::Get()->IsBatterySaverActive());
ASSERT_NE(dark_theme_image, battery_view->GetImageModel());
}
TEST_F(GameDashboardContextTest, MainMenuClockView) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature({features::kGameDashboardUtilities});
CreateGameWindow(true);
task_environment()->AdvanceClock(base::Time::Now().LocalMidnight() +
base::Hours(32) - base::Time::Now());
test_api_->OpenTheMainMenu();
auto* clock_view = test_api_->GetMainMenuClockView();
ASSERT_TRUE(clock_view);
ASSERT_TRUE(clock_view->GetVisible());
ASSERT_EQ(clock_view->GetAmPmClockTypeForTesting(),
base::AmPmClockType::kKeepAmPm);
ASSERT_EQ(clock_view->GetHourTypeForTesting(),
base::HourClockType::k12HourClock);
const auto* horizontal_time_label =
clock_view->GetHorizontalTimeLabelForTesting();
const std::u16string current_time(horizontal_time_label->GetText());
ASSERT_NE(current_time.ends_with(u"AM"), current_time.ends_with(u"PM"));
AdvanceClock(base::Hours(12));
const std::u16string_view next_time = horizontal_time_label->GetText();
const std::u16string next_am_pm =
current_time.ends_with(u"AM") ? u"PM" : u"AM";
ASSERT_NE(current_time, next_time);
ASSERT_TRUE(next_time.ends_with(next_am_pm));
Shell::Get()->system_tray_model()->SetUse24HourClock(true);
ASSERT_TRUE(clock_view->GetVisible());
ASSERT_EQ(clock_view->GetHourTypeForTesting(),
base::HourClockType::k24HourClock);
const auto hour_24_current_time = horizontal_time_label->GetText();
ASSERT_FALSE(hour_24_current_time.ends_with(u"AM") ||
hour_24_current_time.ends_with(u"PM"));
Shell::Get()->system_tray_model()->SetUse24HourClock(false);
ASSERT_TRUE(clock_view->GetVisible());
ASSERT_EQ(clock_view->GetHourTypeForTesting(),
base::HourClockType::k12HourClock);
const auto reverted_current_time = horizontal_time_label->GetText();
ASSERT_NE(reverted_current_time.ends_with(u"AM"),
reverted_current_time.ends_with(u"PM"));
}
TEST_F(GameDashboardContextTest, MainMenuNetworkView) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature({features::kGameDashboardUtilities});
auto network = network_config::CrosNetworkConfigTestHelper::
CreateStandaloneNetworkProperties(
"wifi", chromeos::network_config::mojom::NetworkType::kWiFi,
chromeos::network_config::mojom::ConnectionStateType::kNotConnected);
cros_network()->AddNetworkAndDevice(mojo::Clone(network));
CreateGameWindow(true);
test_api_->OpenTheMainMenu();
auto* network_view = test_api_->GetMainMenuNetworkView();
ASSERT_TRUE(network_view);
auto network_icon = gfx::Image(network_view->GetImage());
network_view->NetworkIconChanged();
EXPECT_NE(network_icon, gfx::Image(network_view->GetImage()));
network_icon = gfx::Image(network_view->GetImage());
network_view->ActiveNetworkStateChanged();
EXPECT_NE(network_icon, gfx::Image(network_view->GetImage()));
network_icon = gfx::Image(network_view->GetImage());
cros_network()->ClearNetworksAndDevices();
network = network_config::CrosNetworkConfigTestHelper::
CreateStandaloneNetworkProperties(
"ethernet", chromeos::network_config::mojom::NetworkType::kEthernet,
chromeos::network_config::mojom::ConnectionStateType::kOnline);
cros_network()->AddNetworkAndDevice(mojo::Clone(network));
EXPECT_NE(network_icon,
gfx::Image(test_api_->GetMainMenuNetworkView()->GetImage()));
}
TEST_F(GameDashboardContextTest, RecordingTimerStringFormat) {
CreateGameWindow(true);
EXPECT_EQ(u"00:00", test_api_->GetRecordingDuration());
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
const auto* record_game_button = test_api_->GetToolbarRecordGameButton();
ASSERT_TRUE(record_game_button);
LeftClickOn(record_game_button);
ClickOnStartRecordingButtonInCaptureModeBarView();
const auto& timer = test_api_->GetRecordingTimer();
EXPECT_TRUE(timer.IsRunning());
EXPECT_EQ(u"00:00", test_api_->GetRecordingDuration());
AdvanceClock(base::Minutes(1));
EXPECT_EQ(u"01:00", test_api_->GetRecordingDuration());
AdvanceClock(base::Seconds(30));
EXPECT_EQ(u"01:30", test_api_->GetRecordingDuration());
AdvanceClock(base::Minutes(50));
EXPECT_EQ(u"51:30", test_api_->GetRecordingDuration());
AdvanceClock(base::Minutes(9));
EXPECT_EQ(u"1:00:30", test_api_->GetRecordingDuration());
AdvanceClock(base::Hours(23));
EXPECT_EQ(u"24:00:30", test_api_->GetRecordingDuration());
LeftClickOn(record_game_button);
EXPECT_EQ(u"00:00", test_api_->GetRecordingDuration());
}
TEST_F(GameDashboardContextTest, WelcomeDialogAutoDismisses) {
game_dashboard_utils::SetShowWelcomeDialog(true);
CreateGameWindow(true,
true);
gfx::Rect welcome_dialog_bounds =
test_api_->GetWelcomeDialogWidget()->GetWindowBoundsInScreen();
EXPECT_EQ(welcome_dialog_bounds.x(),
(game_window_->GetBoundsInScreen().right() -
game_dashboard::kWelcomeDialogEdgePadding -
game_dashboard::kWelcomeDialogFixedWidth -
game_dashboard::kWelcomeDialogBorderThickness * 2));
task_environment()->FastForwardBy(base::Seconds(4));
EXPECT_FALSE(test_api_->GetWelcomeDialogWidget());
}
TEST_F(GameDashboardContextTest, WelcomeDialogDismissOnMainMenuOpening) {
game_dashboard_utils::SetShowWelcomeDialog(true);
CreateGameWindow(true,
true);
test_api_->OpenTheMainMenu();
EXPECT_FALSE(test_api_->GetWelcomeDialogWidget());
}
TEST_F(GameDashboardContextTest, WelcomeDialogWithSmallWindow) {
game_dashboard_utils::SetShowWelcomeDialog(true);
SetAppBounds(gfx::Rect(50, 50, 450, 400));
CreateGameWindow(true,
true);
gfx::Rect welcome_dialog_bounds =
test_api_->GetWelcomeDialogWidget()->GetWindowBoundsInScreen();
EXPECT_EQ(welcome_dialog_bounds.x(),
(game_window_->GetBoundsInScreen().x() +
(game_window_->GetBoundsInScreen().width() -
game_dashboard::kWelcomeDialogFixedWidth -
game_dashboard::kWelcomeDialogBorderThickness * 2) /
2));
}
TEST_F(GameDashboardContextTest, MainMenuCursorHandlerEventLocation) {
SetAppBounds(gfx::Rect(50, 50, 800, 700));
CreateGameWindow(true,
true);
auto* event_generator = GetEventGenerator();
auto* cursor_manager = Shell::Get()->cursor_manager();
event_generator->MoveMouseToCenterOf(game_window_.get());
ASSERT_TRUE(cursor_manager->IsCursorVisible());
cursor_manager->HideCursor();
ASSERT_FALSE(cursor_manager->IsCursorVisible());
ASSERT_FALSE(test_api_->GetMainMenuCursorHandler());
test_api_->OpenTheMainMenu();
ASSERT_TRUE(test_api_->GetMainMenuCursorHandler());
ASSERT_TRUE(cursor_manager->IsCursorVisible());
gfx::Point new_mouse_location =
MoveCursorToEmptySpaceInFrameHeader(test_api_.get());
auto* last_mouse_event = post_target_event_capturer_.last_mouse_event();
ASSERT_TRUE(last_mouse_event);
ASSERT_FALSE(last_mouse_event->handled());
ASSERT_FALSE(last_mouse_event->stopped_propagation());
new_mouse_location.set_x(game_window_->GetBoundsInScreen().CenterPoint().x());
const auto main_menu_bounds =
test_api_->GetMainMenuView()->GetBoundsInScreen();
new_mouse_location.set_y(main_menu_bounds.y() + main_menu_bounds.height() +
50);
post_target_event_capturer_.Reset();
event_generator->MoveMouseTo(new_mouse_location);
ASSERT_FALSE(post_target_event_capturer_.last_mouse_event());
}
TEST_F(GameDashboardContextTest, RecordingUpdatesInkDropColor) {
CreateGameWindow(true,
true);
auto* game_dashboard_button = test_api_->GetGameDashboardButton();
ASSERT_TRUE(game_dashboard_button);
auto* color_provider = game_dashboard_button->GetColorProvider();
ASSERT_TRUE(color_provider);
const auto* ink_drop = views::InkDrop::Get(game_dashboard_button);
ASSERT_TRUE(ink_drop);
EXPECT_EQ(ink_drop->GetBaseColor(),
color_provider->GetColor(cros_tokens::kCrosSysRipplePrimary));
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuRecordGameTile());
base::RunLoop().RunUntilIdle();
ClickOnStartRecordingButtonInCaptureModeBarView();
EXPECT_EQ(
ink_drop->GetBaseColor(),
color_provider->GetColor(cros_tokens::kCrosSysRippleNeutralOnProminent));
}
TEST_F(GameDashboardContextTest, GameDashboardButtonFullscreen) {
SetAppBounds(gfx::Rect(50, 50, 800, 700));
CreateGameWindow(true,
true);
AcceleratorControllerImpl* controller =
Shell::Get()->accelerator_controller();
const ui::Accelerator gd_accelerator(ui::VKEY_G, ui::EF_COMMAND_DOWN);
auto* window_state = WindowState::Get(game_window_.get());
auto* button_widget = test_api_->GetGameDashboardButtonWidget();
CHECK(button_widget);
ASSERT_FALSE(window_state->IsFullscreen());
ASSERT_TRUE(button_widget->IsVisible());
ToggleFullScreen(window_state, nullptr);
ASSERT_TRUE(window_state->IsFullscreen());
ASSERT_FALSE(button_widget->IsVisible());
ASSERT_TRUE(controller->Process(gd_accelerator));
ASSERT_TRUE(button_widget->IsVisible());
ASSERT_TRUE(controller->Process(gd_accelerator));
ASSERT_TRUE(button_widget->IsVisible());
GetEventGenerator()->MoveMouseTo(
game_window_->GetBoundsInScreen().CenterPoint());
ASSERT_FALSE(button_widget->IsVisible());
ToggleFullScreen(window_state, nullptr);
ASSERT_FALSE(window_state->IsFullscreen());
ASSERT_TRUE(button_widget->IsVisible());
}
TEST_F(GameDashboardContextTest, GameDashboardButtonInFullscreen) {
views::Widget* widget =
views::test::TestWidgetBuilder()
.SetBounds(kScreenBounds)
.SetDelegate(CreateTestWidgetBuilderDelegate())
.SetWindowProperty(chromeos::kAppTypeKey, chromeos::AppType::ARC_APP)
.SetShowState(ui::mojom::WindowShowState::kFullscreen)
.BuildOwnedByNativeWidget();
game_window_ = base::WrapUnique(widget->GetNativeWindow());
game_window_->SetProperty(kAppIDKey, TestGameDashboardDelegate::kGameAppId);
test_api_ = std::make_unique<GameDashboardContextTestApi>(
GameDashboardController::Get()->GetGameDashboardContext(
game_window_.get()),
GetEventGenerator());
auto* window_state = WindowState::Get(game_window_.get());
ASSERT_TRUE(window_state->IsFullscreen());
ASSERT_FALSE(test_api_->GetGameDashboardButtonWidget()->IsVisible());
}
TEST_F(GameDashboardContextTest, GameDashboardButtonFullscreenWithMainMenu) {
SetAppBounds(gfx::Rect(50, 50, 800, 700));
CreateGameWindow(true,
true);
AcceleratorControllerImpl* controller =
Shell::Get()->accelerator_controller();
const ui::Accelerator gd_accelerator(ui::VKEY_G, ui::EF_COMMAND_DOWN);
auto* window_state = WindowState::Get(game_window_.get());
auto* button_widget = test_api_->GetGameDashboardButtonWidget();
CHECK(button_widget);
ASSERT_FALSE(window_state->IsFullscreen());
ASSERT_TRUE(button_widget->IsVisible());
GetEventGenerator()->MoveMouseTo(
game_window_->GetBoundsInScreen().CenterPoint());
ASSERT_TRUE(controller->Process(gd_accelerator));
ToggleFullScreen(window_state, nullptr);
ASSERT_TRUE(window_state->IsFullscreen());
ASSERT_TRUE(button_widget->IsVisible());
ASSERT_TRUE(controller->Process(gd_accelerator));
ASSERT_TRUE(button_widget->IsVisible());
GetEventGenerator()->MoveMouseBy(1, 1);
ASSERT_FALSE(button_widget->IsVisible());
}
TEST_F(GameDashboardContextTest,
GameDashboardButtonFullscreen_MouseOverAndTouchGesture) {
CreateAnArcAppAndToggleFullscreen();
views::Widget* button_widget = test_api_->GetGameDashboardButtonWidget();
CHECK(button_widget);
const auto app_bounds = game_window_->GetBoundsInScreen();
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(app_bounds.top_center());
base::OneShotTimer& top_edge_hover_timer =
test_api_->GetRevealControllerTopEdgeHoverTimer();
ASSERT_TRUE(top_edge_hover_timer.IsRunning());
top_edge_hover_timer.FireNow();
ASSERT_TRUE(button_widget->IsVisible());
event_generator->MoveMouseTo(app_bounds.CenterPoint());
ASSERT_FALSE(button_widget->IsVisible());
event_generator->GestureScrollSequence(app_bounds.top_center(),
app_bounds.CenterPoint(),
kTouchDragDuration, kTouchDragSteps);
ASSERT_TRUE(button_widget->IsVisible());
event_generator->GestureScrollSequence(app_bounds.CenterPoint(),
app_bounds.top_center(),
kTouchDragDuration, kTouchDragSteps);
ASSERT_FALSE(button_widget->IsVisible());
event_generator->GestureScrollSequence(app_bounds.top_center(),
app_bounds.CenterPoint(),
kTouchDragDuration, kTouchDragSteps);
ASSERT_TRUE(button_widget->IsVisible());
event_generator->GestureScrollSequence(app_bounds.CenterPoint(),
app_bounds.bottom_center(),
kTouchDragDuration, kTouchDragSteps);
ASSERT_FALSE(button_widget->IsVisible());
event_generator->GestureScrollSequence(app_bounds.CenterPoint(),
app_bounds.bottom_center(),
kTouchDragDuration, kTouchDragSteps);
ASSERT_FALSE(button_widget->IsVisible());
}
TEST_F(GameDashboardContextTest, GameDashboardButtonFullscreen_TouchEvent) {
CreateAnArcAppAndToggleFullscreen();
views::Widget* button_widget = test_api_->GetGameDashboardButtonWidget();
CHECK(button_widget);
const auto app_bounds = game_window_->GetBoundsInScreen();
auto* event_generator = GetEventGenerator();
event_generator->MoveMouseTo(app_bounds.top_center());
base::OneShotTimer& top_edge_hover_timer =
test_api_->GetRevealControllerTopEdgeHoverTimer();
ASSERT_TRUE(top_edge_hover_timer.IsRunning());
top_edge_hover_timer.FireNow();
ASSERT_TRUE(button_widget->IsVisible());
event_generator->PressTouch(app_bounds.right_center());
event_generator->ReleaseTouch();
ASSERT_FALSE(button_widget->IsVisible());
}
TEST_F(GameDashboardContextTest, NoCrashOnWindowDestroyInFullscreen) {
CreateAnArcAppAndToggleFullscreen();
ASSERT_TRUE(test_api_->GetGameDashboardButtonRevealController());
CloseGameWindow();
SUCCEED() << "Window destroyed in fullscreen without crashing.";
}
TEST_F(GameDashboardContextTest,
GameDashboardOverviewModeStaticWidgetPosition_ZoomEvent) {
CreateGameWindow(true);
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
EnterOverview();
Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
AcceleratorAction::kScaleUiDown, {});
ExitOverview();
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kTopRight);
const gfx::Point expected_button_center_point(
game_window_->GetBoundsInScreen().top_center().x(),
app_bounds().y() + frame_header_height_ / 2);
EXPECT_EQ(expected_button_center_point,
test_api_->GetGameDashboardButtonWidget()
->GetNativeWindow()
->GetBoundsInScreen()
.CenterPoint());
}
TEST_F(GameDashboardContextTest, UIVisibilityWithWindowSnapAnimation) {
gfx::ScopedAnimationDurationScaleMode test_duration_mode(
gfx::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
CreateGameWindow(true);
ui::LayerAnimator* animator = game_window_->layer()->GetAnimator();
animator->set_disable_timer_for_test(true);
const auto* game_dashboard_button_widget =
test_api_->GetGameDashboardButtonWidget();
ASSERT_TRUE(game_dashboard_button_widget);
ASSERT_TRUE(game_dashboard_button_widget->IsVisible());
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
AcceleratorAction::kWindowCycleSnapLeft, {});
ASSERT_TRUE(animator->is_animating());
animator->Step(animator->last_step_time() + base::Milliseconds(10));
ASSERT_FALSE(game_dashboard_button_widget->IsVisible());
const auto* toolbar_widget = test_api_->GetToolbarWidget();
ASSERT_FALSE(toolbar_widget->IsVisible());
animator->StopAnimating();
ASSERT_FALSE(animator->is_animating());
ASSERT_TRUE(game_dashboard_button_widget->IsVisible());
ASSERT_TRUE(toolbar_widget->IsVisible());
ASSERT_TRUE(WindowState::Get(game_window_.get())->IsSnapped());
}
TEST_F(GameDashboardContextTest, UIVisibilityWithWindowFloatAnimation) {
gfx::ScopedAnimationDurationScaleMode test_duration_mode(
gfx::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
CreateGameWindow(true);
ui::LayerAnimator* animator = game_window_->layer()->GetAnimator();
animator->set_disable_timer_for_test(true);
const auto* game_dashboard_button_widget =
test_api_->GetGameDashboardButtonWidget();
ASSERT_TRUE(game_dashboard_button_widget);
ASSERT_TRUE(game_dashboard_button_widget->IsVisible());
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
ASSERT_TRUE(animator->is_animating());
animator->Step(animator->last_step_time() + base::Milliseconds(10));
ASSERT_FALSE(game_dashboard_button_widget->IsVisible());
ASSERT_FALSE(test_api_->GetToolbarWidget()->IsVisible());
ShellTestApi().WaitForWindowFinishAnimating(game_window_.get());
EXPECT_TRUE(game_dashboard_button_widget->IsVisible());
ASSERT_TRUE(test_api_->GetToolbarWidget()->IsVisible());
ASSERT_TRUE(WindowState::Get(game_window_.get())->IsFloated());
}
TEST_F(GameDashboardContextTest, MainMenuAndToolbarAndWelcomeDialogStartup) {
game_dashboard_utils::SetShowWelcomeDialog(true);
game_dashboard_utils::SetShowToolbar(true);
CreateGameWindow(true);
ASSERT_TRUE(test_api_->GetWelcomeDialogWidget());
ASSERT_FALSE(test_api_->GetToolbarWidget());
task_environment()->FastForwardBy(base::Seconds(1));
ASSERT_TRUE(test_api_->GetWelcomeDialogWidget());
ASSERT_FALSE(test_api_->GetToolbarWidget());
test_api_->OpenTheMainMenu();
ASSERT_FALSE(test_api_->GetWelcomeDialogWidget());
ASSERT_TRUE(test_api_->GetToolbarWidget());
}
TEST_F(GameDashboardContextTest, OverviewModeWithTwoWindows) {
game_dashboard_utils::SetShowToolbar(true);
std::unique_ptr<aura::Window> gfn_game_window =
CreateAppWindow(extension_misc::kGeForceNowAppId,
chromeos::AppType::NON_APP, gfx::Rect(50, 50, 400, 200));
ASSERT_TRUE(gfn_game_window->HasFocus());
auto gfn_window_test_api = GameDashboardContextTestApi(
GameDashboardController::Get()->GetGameDashboardContext(
gfn_game_window.get()),
GetEventGenerator());
ASSERT_TRUE(gfn_window_test_api.GetToolbarWidget());
CreateGameWindow(true);
auto* arc_game_window = game_window_.get();
auto arc_window_test_api = GameDashboardContextTestApi(
GameDashboardController::Get()->GetGameDashboardContext(arc_game_window),
GetEventGenerator());
ASSERT_TRUE(arc_window_test_api.GetToolbarWidget());
ASSERT_FALSE(gfn_game_window->HasFocus());
ASSERT_TRUE(arc_game_window->HasFocus());
const auto* arc_gamepad_button =
arc_window_test_api.GetToolbarGamepadButton();
ASSERT_TRUE(arc_gamepad_button);
LeftClickOn(arc_gamepad_button);
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_TAB);
ASSERT_FALSE(arc_game_window->HasFocus());
ASSERT_TRUE(arc_gamepad_button->HasFocus());
EnterOverview();
ExitOverview();
ASSERT_FALSE(gfn_game_window->HasFocus());
ASSERT_TRUE(arc_game_window->HasFocus());
ASSERT_FALSE(arc_gamepad_button->HasFocus());
}
TEST_F(GameDashboardContextTest, TabNavigationMainMenu) {
CreateGameWindow(false);
test_api_->OpenTheMainMenu();
TabNavigateForward();
views::Widget* main_menu_widget = test_api_->GetMainMenuWidget();
EXPECT_TRUE(main_menu_widget->IsActive());
EXPECT_TRUE(test_api_->GetMainMenuToolbarTile()->HasFocus());
main_menu_widget->GetFocusManager()->SetFocusedView(
test_api_->GetMainMenuSettingsButton());
EXPECT_TRUE(test_api_->GetMainMenuSettingsButton()->HasFocus());
TabNavigateForward();
EXPECT_TRUE(test_api_->GetGameDashboardButton()->HasFocus());
TabNavigateForward();
EXPECT_TRUE(test_api_->GetMainMenuToolbarTile()->HasFocus());
TabNavigateBackward();
EXPECT_TRUE(test_api_->GetGameDashboardButton()->HasFocus());
TabNavigateBackward();
EXPECT_TRUE(test_api_->GetMainMenuSettingsButton()->HasFocus());
}
TEST_F(GameDashboardContextTest, TabNavigationMainMenuAndToolbar) {
CreateGameWindow(false);
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
TabNavigateForward();
views::Widget* main_menu_widget = test_api_->GetMainMenuWidget();
ASSERT_TRUE(main_menu_widget->IsActive());
ASSERT_TRUE(test_api_->GetMainMenuToolbarTile()->HasFocus());
main_menu_widget->GetFocusManager()->SetFocusedView(
test_api_->GetMainMenuSettingsButton());
ASSERT_TRUE(test_api_->GetMainMenuSettingsButton()->HasFocus());
TabNavigateForward();
views::Widget* toolbar_widget = test_api_->GetToolbarWidget();
EXPECT_TRUE(toolbar_widget->IsActive());
EXPECT_TRUE(test_api_->GetToolbarGamepadButton()->HasFocus());
toolbar_widget->GetFocusManager()->SetFocusedView(
test_api_->GetToolbarScreenshotButton());
TabNavigateForward();
EXPECT_TRUE(test_api_->GetGameDashboardButton()->HasFocus());
TabNavigateForward();
EXPECT_TRUE(test_api_->GetMainMenuToolbarTile()->HasFocus());
TabNavigateBackward();
EXPECT_TRUE(test_api_->GetGameDashboardButton()->HasFocus());
TabNavigateBackward();
EXPECT_TRUE(test_api_->GetToolbarScreenshotButton()->HasFocus());
toolbar_widget->GetFocusManager()->SetFocusedView(
test_api_->GetToolbarGamepadButton());
TabNavigateBackward();
EXPECT_TRUE(test_api_->GetMainMenuSettingsButton()->HasFocus());
test_api_->CloseTheToolbar();
TabNavigateForward();
EXPECT_TRUE(test_api_->GetGameDashboardButton()->HasFocus());
test_api_->CloseTheMainMenu();
}
TEST_F(GameDashboardContextTest, TabNavigationToolbar) {
CreateGameWindow(false);
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
test_api_->CloseTheMainMenu();
test_api_->SetFocusOnToolbar();
ASSERT_TRUE(test_api_->IsToolbarExpanded());
TabNavigateForward();
views::Widget* toolbar_widget = test_api_->GetToolbarWidget();
EXPECT_TRUE(toolbar_widget->IsActive());
EXPECT_TRUE(test_api_->GetToolbarGamepadButton()->HasFocus());
toolbar_widget->GetFocusManager()->SetFocusedView(
test_api_->GetToolbarScreenshotButton());
ASSERT_TRUE(test_api_->GetToolbarScreenshotButton()->HasFocus());
TabNavigateForward();
EXPECT_TRUE(test_api_->GetGameDashboardButton()->HasFocus());
TabNavigateForward();
EXPECT_TRUE(test_api_->GetToolbarGamepadButton()->HasFocus());
TabNavigateBackward();
EXPECT_TRUE(test_api_->GetGameDashboardButton()->HasFocus());
TabNavigateBackward();
EXPECT_TRUE(test_api_->GetToolbarScreenshotButton()->HasFocus());
}
using SnapGroupGameDashboardContextTest = GameDashboardContextTest;
TEST_F(SnapGroupGameDashboardContextTest, NoCrashOnSnapGroupWorkAreaChange) {
CreateGameWindow(false);
std::unique_ptr<aura::Window> w2(AshTestBase::CreateAppWindow());
WindowState* window_state2 = WindowState::Get(w2.get());
const WindowSnapWMEvent secondary_snap_event(
WM_EVENT_SNAP_SECONDARY, chromeos::kDefaultSnapRatio,
WindowSnapActionSource::kSnapByWindowLayoutMenu);
window_state2->OnWMEvent(&secondary_snap_event);
EXPECT_TRUE(window_state2->IsSnapped());
WindowState* window_state1 = WindowState::Get(game_window_.get());
const WindowSnapWMEvent primary_snap_event(
WM_EVENT_SNAP_PRIMARY, chromeos::kDefaultSnapRatio,
WindowSnapActionSource::kSnapByWindowLayoutMenu);
window_state1->OnWMEvent(&primary_snap_event);
EXPECT_TRUE(window_state1->IsSnapped());
ASSERT_TRUE(SnapGroupController::Get()->AreWindowsInSnapGroup(
game_window_.get(), w2.get()));
ASSERT_TRUE(test_api_->GetGameDashboardButtonWidget()->IsVisible());
wm::ActivateWindow(game_window_.get());
ToggleFullScreen(window_state1, nullptr);
}
class GameTypeGameDashboardContextTest
: public GameDashboardContextTest,
public testing::WithParamInterface<bool> {
public:
GameTypeGameDashboardContextTest() = default;
~GameTypeGameDashboardContextTest() override = default;
void SetUp() override {
GameDashboardContextTest::SetUp();
CreateGameWindow(IsArcGame());
}
protected:
bool IsArcGame() const { return GetParam(); }
void VerifyFeaturesEnabled(bool expect_enabled,
bool toolbar_visible = false) {
auto* event_generator = GetEventGenerator();
auto* gd_button_widget = test_api_->GetGameDashboardButtonWidget();
EXPECT_TRUE(gd_button_widget);
if (expect_enabled) {
EXPECT_TRUE(gd_button_widget->IsVisible());
event_generator->PressAndReleaseKey(ui::VKEY_G, ui::EF_COMMAND_DOWN);
EXPECT_TRUE(test_api_->GetMainMenuWidget());
test_api_->CloseTheMainMenu();
} else {
EXPECT_FALSE(gd_button_widget->IsVisible());
event_generator->PressAndReleaseKey(ui::VKEY_G, ui::EF_COMMAND_DOWN);
EXPECT_FALSE(test_api_->GetMainMenuWidget());
}
auto* toolbar_widget = test_api_->GetToolbarWidget();
if (toolbar_visible) {
EXPECT_TRUE(toolbar_widget);
EXPECT_TRUE(toolbar_widget->IsVisible());
} else {
EXPECT_TRUE(!toolbar_widget || !toolbar_widget->IsVisible());
}
}
};
TEST_P(GameTypeGameDashboardContextTest, DefaultWidgetStartupSequence) {
CloseGameWindow();
auto* active_user_prefs_ =
Shell::Get()->session_controller()->GetActivePrefService();
ASSERT_TRUE(active_user_prefs_);
active_user_prefs_->ClearPref(prefs::kGameDashboardShowToolbar);
active_user_prefs_->ClearPref(prefs::kGameDashboardShowWelcomeDialog);
ASSERT_FALSE(game_dashboard_utils::ShouldShowToolbar());
ASSERT_TRUE(game_dashboard_utils::ShouldShowWelcomeDialog());
CreateGameWindow(IsArcGame());
ASSERT_TRUE(test_api_->GetWelcomeDialogWidget());
ASSERT_FALSE(test_api_->GetToolbarWidget());
task_environment()->FastForwardBy(base::Seconds(4));
ASSERT_FALSE(test_api_->GetWelcomeDialogWidget());
ASSERT_FALSE(test_api_->GetToolbarWidget());
}
TEST_P(GameTypeGameDashboardContextTest,
GameDashboardButtonWidget_InitialLocation) {
const gfx::Point expected_button_center_point(
game_window_->GetBoundsInScreen().top_center().x(),
app_bounds().y() + frame_header_height_ / 2);
EXPECT_EQ(expected_button_center_point,
test_api_->GetGameDashboardButtonWidget()
->GetNativeWindow()
->GetBoundsInScreen()
.CenterPoint());
}
TEST_P(GameTypeGameDashboardContextTest,
GameDashboardButtonWidget_MoveWindowAndVerifyLocation) {
const auto move_vector = gfx::Vector2d(100, 200);
const auto* native_window =
test_api_->GetGameDashboardButtonWidget()->GetNativeWindow();
const auto expected_widget_location =
native_window->GetBoundsInScreen() + move_vector;
game_window_->SetBoundsInScreen(
game_window_->GetBoundsInScreen() + move_vector, GetPrimaryDisplay());
EXPECT_EQ(expected_widget_location, native_window->GetBoundsInScreen());
}
TEST_P(GameTypeGameDashboardContextTest, OpenGameDashboardButtonWidget) {
CloseGameWindow();
CreateGameWindow(IsArcGame(), false);
EXPECT_FALSE(test_api_->GetMainMenuWidget());
if (IsArcGame()) {
EXPECT_FALSE(test_api_->GetGameDashboardButton()->GetEnabled());
LeftClickOn(test_api_->GetGameDashboardButton());
EXPECT_FALSE(test_api_->GetMainMenuWidget());
game_window_->SetProperty(kArcGameControlsFlagsKey,
ArcGameControlsFlag::kKnown);
}
test_api_->OpenTheMainMenu();
}
TEST_P(GameTypeGameDashboardContextTest, GameControlsUiExistence) {
const bool is_arc_game = IsArcGame();
if (is_arc_game) {
game_window_->SetProperty(kArcGameControlsFlagsKey,
ArcGameControlsFlag::kKnown);
}
OpenMenuCheckGameControlsUIState(
{is_arc_game, false,
false},
{is_arc_game, false},
{false, false},
is_arc_game);
}
TEST_P(GameTypeGameDashboardContextTest, CloseGameDashboardButtonWidget) {
test_api_->OpenTheMainMenu();
test_api_->CloseTheMainMenu();
}
TEST_P(GameTypeGameDashboardContextTest, CloseMainMenuViaEscapeButton) {
test_api_->OpenTheMainMenu();
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_ESCAPE);
base::RunLoop().RunUntilIdle();
test_api_->VerifyAccessibilityTree();
test_api_->OpenTheMainMenu();
test_api_->CloseTheMainMenu();
}
TEST_P(GameTypeGameDashboardContextTest, CloseMainMenuOutsideButtonWidget) {
test_api_->OpenTheMainMenu();
auto* event_generator = GetEventGenerator();
gfx::Rect game_bounds = app_bounds();
const gfx::Point& new_location = {game_bounds.x() + game_bounds.width(),
game_bounds.y() + game_bounds.height()};
event_generator->set_current_screen_location(new_location);
event_generator->ClickLeftButton();
base::RunLoop().RunUntilIdle();
test_api_->VerifyAccessibilityTree();
test_api_->OpenTheMainMenu();
test_api_->CloseTheMainMenu();
}
TEST_P(GameTypeGameDashboardContextTest,
MainMenuDialogWidget_AvailableFeatures) {
if (IsArcGame()) {
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(ArcGameControlsFlag::kKnown |
ArcGameControlsFlag::kAvailable));
}
test_api_->OpenTheMainMenu();
EXPECT_TRUE(test_api_->GetMainMenuToolbarTile());
EXPECT_TRUE(test_api_->GetMainMenuRecordGameTile());
EXPECT_TRUE(test_api_->GetMainMenuScreenshotTile());
EXPECT_TRUE(test_api_->GetMainMenuFeedbackButton());
EXPECT_TRUE(test_api_->GetMainMenuHelpButton());
EXPECT_TRUE(test_api_->GetMainMenuSettingsButton());
if (IsArcGame()) {
EXPECT_TRUE(test_api_->GetMainMenuGameControlsTile());
EXPECT_TRUE(test_api_->GetMainMenuScreenSizeSettingsButton());
} else {
EXPECT_FALSE(test_api_->GetMainMenuGameControlsTile());
EXPECT_FALSE(test_api_->GetMainMenuScreenSizeSettingsButton());
}
}
TEST_P(GameTypeGameDashboardContextTest,
MainMenuDialogWidget_RecordGameDisabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(
{features::kFeatureManagementGameDashboardRecordGame});
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
EXPECT_FALSE(test_api_->GetMainMenuRecordGameTile());
EXPECT_FALSE(test_api_->GetToolbarRecordGameButton());
}
TEST_P(GameTypeGameDashboardContextTest, TakeScreenshotFromMainMenu) {
test_api_->OpenTheMainMenu();
const auto* screenshot_tile = test_api_->GetMainMenuScreenshotTile();
ASSERT_TRUE(screenshot_tile);
LeftClickOn(screenshot_tile);
const auto file_path = WaitForCaptureFileToBeSaved();
const auto image = ReadAndDecodeImageFile(file_path);
EXPECT_EQ(image.Size(), game_window_->bounds().size());
}
TEST_P(GameTypeGameDashboardContextTest,
CaptureSessionStartedOutsideOfTheGameDashboard) {
test_api_->OpenTheMainMenu();
VerifyGameDashboardButtonState(false);
const auto* main_menu_record_game_button =
test_api_->GetMainMenuRecordGameTile();
EXPECT_TRUE(main_menu_record_game_button);
EXPECT_TRUE(main_menu_record_game_button->GetEnabled());
EXPECT_FALSE(main_menu_record_game_button->IsToggled());
test_api_->OpenTheToolbar();
const auto* toolbar_record_game_button =
test_api_->GetToolbarRecordGameButton();
EXPECT_TRUE(toolbar_record_game_button);
EXPECT_TRUE(toolbar_record_game_button->GetEnabled());
EXPECT_FALSE(toolbar_record_game_button->toggled());
const auto* capture_mode_controller = CaptureModeController::Get();
EXPECT_FALSE(capture_mode_controller->is_recording_in_progress());
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kVideo);
StartVideoRecordingImmediately();
EXPECT_TRUE(capture_mode_controller->is_recording_in_progress());
EXPECT_FALSE(main_menu_record_game_button->GetEnabled());
EXPECT_FALSE(main_menu_record_game_button->IsToggled());
EXPECT_FALSE(toolbar_record_game_button->GetEnabled());
EXPECT_FALSE(toolbar_record_game_button->toggled());
VerifyGameDashboardButtonState(false);
CaptureModeTestApi().StopVideoRecording();
EXPECT_FALSE(capture_mode_controller->is_recording_in_progress());
EXPECT_FALSE(capture_mode_controller->can_start_new_recording());
EXPECT_FALSE(main_menu_record_game_button->GetEnabled());
EXPECT_FALSE(main_menu_record_game_button->IsToggled());
EXPECT_FALSE(toolbar_record_game_button->GetEnabled());
EXPECT_FALSE(toolbar_record_game_button->toggled());
WaitForCaptureFileToBeSaved();
EXPECT_TRUE(capture_mode_controller->can_start_new_recording());
EXPECT_TRUE(main_menu_record_game_button->GetEnabled());
EXPECT_FALSE(main_menu_record_game_button->IsToggled());
EXPECT_TRUE(toolbar_record_game_button->GetEnabled());
EXPECT_FALSE(toolbar_record_game_button->toggled());
VerifyGameDashboardButtonState(false);
}
TEST_P(GameTypeGameDashboardContextTest, OpenAndCloseToolbarWidget) {
if (IsArcGame()) {
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(ArcGameControlsFlag::kKnown |
ArcGameControlsFlag::kAvailable));
}
test_api_->OpenTheMainMenu();
auto* toolbar_tile = test_api_->GetMainMenuToolbarTile();
ASSERT_TRUE(toolbar_tile);
EXPECT_FALSE(toolbar_tile->IsToggled());
EXPECT_EQ(toolbar_tile->sub_label()->GetText(), hidden_label);
test_api_->OpenTheToolbar();
EXPECT_EQ(toolbar_tile->sub_label()->GetText(), visible_label);
EXPECT_TRUE(test_api_->GetToolbarGamepadButton());
EXPECT_TRUE(test_api_->GetToolbarRecordGameButton());
EXPECT_TRUE(test_api_->GetToolbarScreenshotButton());
EXPECT_TRUE(test_api_->GetMainMenuWidget()->IsStackedAbove(
test_api_->GetToolbarWidget()->GetNativeView()));
if (IsArcGame()) {
EXPECT_TRUE(test_api_->GetToolbarGameControlsButton());
} else {
EXPECT_FALSE(test_api_->GetToolbarGameControlsButton());
}
test_api_->CloseTheMainMenu();
EXPECT_TRUE(test_api_->GetToolbarWidget());
test_api_->OpenTheMainMenu();
toolbar_tile = test_api_->GetMainMenuToolbarTile();
EXPECT_EQ(toolbar_tile->sub_label()->GetText(), visible_label);
EXPECT_TRUE(test_api_->GetToolbarWidget());
EXPECT_TRUE(test_api_->GetMainMenuWidget()->IsStackedAbove(
test_api_->GetToolbarWidget()->GetNativeView()));
test_api_->CloseTheToolbar();
EXPECT_FALSE(test_api_->GetToolbarWidget());
EXPECT_FALSE(toolbar_tile->IsToggled());
EXPECT_EQ(toolbar_tile->sub_label()->GetText(), hidden_label);
}
TEST_P(GameTypeGameDashboardContextTest, TakeScreenshotFromToolbar) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
const auto* screenshot_button = test_api_->GetToolbarScreenshotButton();
ASSERT_TRUE(screenshot_button);
LeftClickOn(screenshot_button);
const auto file_path = WaitForCaptureFileToBeSaved();
const auto image = ReadAndDecodeImageFile(file_path);
EXPECT_EQ(image.Size(), game_window_->GetBoundsInScreen().size());
}
TEST_P(GameTypeGameDashboardContextTest, CollapseAndExpandToolbarWidget) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
const int initial_height = GetToolbarHeight();
EXPECT_NE(initial_height, 0);
auto* gamepad_button = test_api_->GetToolbarGamepadButton();
ASSERT_TRUE(gamepad_button);
LeftClickOn(gamepad_button);
int updated_height = GetToolbarHeight();
EXPECT_GT(initial_height, updated_height);
LeftClickOn(gamepad_button);
updated_height = GetToolbarHeight();
EXPECT_EQ(initial_height, updated_height);
}
TEST_P(GameTypeGameDashboardContextTest, MoveToolbarOutOfBounds) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
ASSERT_TRUE(test_api_->GetToolbarWidget());
ASSERT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kTopRight);
auto window_bounds = game_window_->GetBoundsInScreen();
const int screen_point_x = kScreenBounds.x();
const int screen_point_right = screen_point_x + kScreenBounds.width();
const int screen_point_y = kScreenBounds.y();
const int screen_point_bottom = screen_point_y + kScreenBounds.height();
auto game_bounds = app_bounds();
ASSERT_LT(screen_point_x, game_bounds.x());
ASSERT_LT(screen_point_y, game_bounds.y());
ASSERT_GT(screen_point_right, game_bounds.x() + game_bounds.width());
ASSERT_GT(screen_point_bottom, game_bounds.y() + game_bounds.height());
DragToolbarToPoint(Movement::kMouse, {screen_point_right, screen_point_y},
false);
const auto* native_window = test_api_->GetToolbarWidget()->GetNativeWindow();
auto toolbar_bounds = native_window->GetBoundsInScreen();
EXPECT_EQ(toolbar_bounds.right(), window_bounds.right());
EXPECT_EQ(toolbar_bounds.y(), window_bounds.y());
DragToolbarToPoint(Movement::kMouse, {screen_point_x, screen_point_y}, false);
toolbar_bounds = native_window->GetBoundsInScreen();
EXPECT_EQ(toolbar_bounds.x(), window_bounds.x());
EXPECT_EQ(toolbar_bounds.y(), window_bounds.y());
DragToolbarToPoint(Movement::kMouse, {screen_point_x, screen_point_bottom},
false);
toolbar_bounds = native_window->GetBoundsInScreen();
EXPECT_EQ(toolbar_bounds.x(), window_bounds.x());
EXPECT_EQ(toolbar_bounds.bottom(), window_bounds.bottom());
DragToolbarToPoint(Movement::kMouse,
{screen_point_right, screen_point_bottom}, false);
toolbar_bounds = native_window->GetBoundsInScreen();
EXPECT_EQ(toolbar_bounds.right(), window_bounds.right());
EXPECT_EQ(toolbar_bounds.bottom(), window_bounds.bottom());
GetEventGenerator()->ReleaseLeftButton();
}
TEST_P(GameTypeGameDashboardContextTest, MoveToolbarWidgetViaMouse) {
VerifyToolbarDrag(Movement::kMouse);
}
TEST_P(GameTypeGameDashboardContextTest, MoveToolbarWidgetViaTouch) {
VerifyToolbarDrag(Movement::kTouch);
}
TEST_P(GameTypeGameDashboardContextTest, MoveToolbarWidgetViaArrowKeys) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
test_api_->SetFocusOnToolbar();
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kTopRight);
GetEventGenerator()->PressAndReleaseKey(ui::VKEY_TAB);
PressKeyAndVerify(ui::VKEY_RIGHT,
GameDashboardToolbarSnapLocation::kTopRight);
PressKeyAndVerify(ui::VKEY_LEFT, GameDashboardToolbarSnapLocation::kTopLeft);
PressKeyAndVerify(ui::VKEY_DOWN,
GameDashboardToolbarSnapLocation::kBottomLeft);
PressKeyAndVerify(ui::VKEY_RIGHT,
GameDashboardToolbarSnapLocation::kBottomRight);
PressKeyAndVerify(ui::VKEY_UP, GameDashboardToolbarSnapLocation::kTopRight);
PressKeyAndVerify(ui::VKEY_UP, GameDashboardToolbarSnapLocation::kTopRight);
PressKeyAndVerify(ui::VKEY_DOWN,
GameDashboardToolbarSnapLocation::kBottomRight);
PressKeyAndVerify(ui::VKEY_DOWN,
GameDashboardToolbarSnapLocation::kBottomRight);
PressKeyAndVerify(ui::VKEY_LEFT,
GameDashboardToolbarSnapLocation::kBottomLeft);
PressKeyAndVerify(ui::VKEY_UP, GameDashboardToolbarSnapLocation::kTopLeft);
PressKeyAndVerify(ui::VKEY_RIGHT,
GameDashboardToolbarSnapLocation::kTopRight);
}
TEST_P(GameTypeGameDashboardContextTest, VerifyToolbarPlacementInQuadrants) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
const auto window_bounds = game_window_->GetBoundsInScreen();
const auto window_center_point = window_bounds.CenterPoint();
const int x_offset = window_bounds.width() / 4;
const int y_offset = window_bounds.height() / 4;
auto game_bounds = app_bounds();
const auto* native_window = test_api_->GetToolbarWidget()->GetNativeWindow();
auto toolbar_bounds = native_window->GetBoundsInScreen();
const auto toolbar_size =
test_api_->GetToolbarWidget()->GetContentsView()->GetPreferredSize();
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kTopRight);
EXPECT_EQ(toolbar_bounds.x(), game_bounds.right() -
game_dashboard::kToolbarEdgePadding -
toolbar_size.width());
EXPECT_EQ(toolbar_bounds.y(), game_bounds.y() +
game_dashboard::kToolbarEdgePadding +
frame_header_height_);
DragToolbarToPoint(Movement::kMouse, {window_center_point.x() - x_offset,
window_center_point.y() - y_offset});
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kTopLeft);
toolbar_bounds = native_window->GetBoundsInScreen();
EXPECT_EQ(toolbar_bounds.x(),
game_bounds.x() + game_dashboard::kToolbarEdgePadding);
EXPECT_EQ(toolbar_bounds.y(), game_bounds.y() +
game_dashboard::kToolbarEdgePadding +
frame_header_height_);
DragToolbarToPoint(Movement::kMouse, {window_center_point.x() + x_offset,
window_center_point.y() + y_offset});
toolbar_bounds = native_window->GetBoundsInScreen();
EXPECT_EQ(toolbar_bounds.x(), game_bounds.right() -
game_dashboard::kToolbarEdgePadding -
toolbar_size.width());
EXPECT_EQ(toolbar_bounds.y(), game_bounds.bottom() -
game_dashboard::kToolbarEdgePadding -
toolbar_size.height());
DragToolbarToPoint(Movement::kMouse, {window_center_point.x() - x_offset,
window_center_point.y() + y_offset});
toolbar_bounds = native_window->GetBoundsInScreen();
EXPECT_EQ(toolbar_bounds.x(),
game_bounds.x() + game_dashboard::kToolbarEdgePadding);
EXPECT_EQ(toolbar_bounds.y(), game_bounds.bottom() -
game_dashboard::kToolbarEdgePadding -
toolbar_size.height());
}
TEST_P(GameTypeGameDashboardContextTest, MoveAndHideToolbarWidget) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
const auto window_bounds = game_window_->GetBoundsInScreen();
const auto window_center_point = window_bounds.CenterPoint();
DragToolbarToPoint(Movement::kMouse,
{window_center_point.x() - (window_bounds.width() / 4),
window_center_point.y() + (window_bounds.height() / 4)});
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kBottomLeft);
test_api_->OpenTheMainMenu();
test_api_->CloseTheToolbar();
test_api_->OpenTheToolbar();
EXPECT_EQ(test_api_->GetToolbarSnapLocation(),
GameDashboardToolbarSnapLocation::kBottomLeft);
}
TEST_P(GameTypeGameDashboardContextTest, OpenAndCloseSettingsView) {
test_api_->OpenTheMainMenu();
test_api_->OpenMainMenuSettings();
test_api_->CloseTheSettings();
auto* main_menu_container = test_api_->GetMainMenuContainer();
EXPECT_TRUE(test_api_->GetMainMenuView());
EXPECT_TRUE(main_menu_container && main_menu_container->GetVisible());
test_api_->OpenMainMenuSettings();
test_api_->CloseTheMainMenu();
}
TEST_P(GameTypeGameDashboardContextTest, ToggleWelcomeDialogSettings) {
test_api_->OpenTheMainMenu();
test_api_->OpenMainMenuSettings();
EXPECT_FALSE(test_api_->GetSettingsViewWelcomeDialogSwitch()->GetIsOn());
test_api_->ToggleWelcomeDialogSettingsSwitch();
EXPECT_TRUE(test_api_->GetSettingsViewWelcomeDialogSwitch()->GetIsOn());
test_api_->CloseTheMainMenu();
test_api_->OpenTheMainMenu();
test_api_->OpenMainMenuSettings();
EXPECT_TRUE(test_api_->GetSettingsViewWelcomeDialogSwitch()->GetIsOn());
}
TEST_P(GameTypeGameDashboardContextTest, TabletMode) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
ash::TabletModeControllerTestApi().EnterTabletMode();
ASSERT_TRUE(display::Screen::Get()->InTabletMode());
VerifyFeaturesEnabled(false);
EXPECT_TRUE(
ToastManager::Get()->IsToastShown(game_dashboard::kTabletToastId));
ash::TabletModeControllerTestApi().LeaveTabletMode();
ASSERT_FALSE(display::Screen::Get()->InTabletMode());
VerifyFeaturesEnabled(true, true);
EXPECT_FALSE(
ToastManager::Get()->IsToastShown(game_dashboard::kTabletToastId));
CloseGameWindow();
ash::TabletModeControllerTestApi().EnterTabletMode();
ASSERT_TRUE(display::Screen::Get()->InTabletMode());
EXPECT_FALSE(
ToastManager::Get()->IsToastShown(game_dashboard::kTabletToastId));
CreateGameWindow(IsArcGame());
VerifyFeaturesEnabled(false);
EXPECT_FALSE(
ToastManager::Get()->IsToastShown(game_dashboard::kTabletToastId));
ash::TabletModeControllerTestApi().LeaveTabletMode();
ASSERT_FALSE(display::Screen::Get()->InTabletMode());
VerifyFeaturesEnabled(true);
EXPECT_FALSE(
ToastManager::Get()->IsToastShown(game_dashboard::kTabletToastId));
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuRecordGameTile());
base::RunLoop().RunUntilIdle();
ClickOnStartRecordingButtonInCaptureModeBarView();
EXPECT_TRUE(CaptureModeController::Get()->is_recording_in_progress());
ash::TabletModeControllerTestApi().EnterTabletMode();
EXPECT_FALSE(CaptureModeController::Get()->is_recording_in_progress());
EXPECT_TRUE(
ToastManager::Get()->IsToastShown(game_dashboard::kTabletToastId));
}
TEST_P(GameTypeGameDashboardContextTest, TabNavigationGameWindow) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
test_api_->CloseTheMainMenu();
aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow())
->FocusWindow(game_window_.get());
TabNavigateForward();
EXPECT_FALSE(test_api_->GetGameDashboardButton()->HasFocus());
EXPECT_FALSE(test_api_->GetToolbarGamepadButton()->HasFocus());
}
class OnOverviewModeEndedWaiter : public OverviewObserver {
public:
OnOverviewModeEndedWaiter()
: overview_controller_(OverviewController::Get()) {
CHECK(overview_controller_);
overview_controller_->AddObserver(this);
}
OnOverviewModeEndedWaiter(const OnOverviewModeEndedWaiter&) = delete;
OnOverviewModeEndedWaiter& operator=(const OnOverviewModeEndedWaiter&) =
delete;
~OnOverviewModeEndedWaiter() override {
overview_controller_->RemoveObserver(this);
}
void Wait() { run_loop_.Run(); }
void OnOverviewModeEnded() override { run_loop_.Quit(); }
private:
base::RunLoop run_loop_;
const raw_ptr<OverviewController> overview_controller_;
};
TEST_P(GameTypeGameDashboardContextTest, OverviewMode) {
auto* game_dashboard_button_widget =
test_api_->GetGameDashboardButtonWidget();
ASSERT_TRUE(game_dashboard_button_widget);
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
EXPECT_TRUE(game_dashboard_button_widget->IsVisible());
const auto* toolbar_widget = test_api_->GetToolbarWidget();
ASSERT_TRUE(toolbar_widget);
EXPECT_TRUE(toolbar_widget->IsVisible());
const auto* main_menu_widget = test_api_->GetMainMenuWidget();
ASSERT_TRUE(main_menu_widget);
EXPECT_TRUE(main_menu_widget->IsVisible());
EnterOverview();
const auto* overview_controller = OverviewController::Get();
ASSERT_TRUE(overview_controller->InOverviewSession());
EXPECT_FALSE(game_dashboard_button_widget->IsVisible());
ASSERT_EQ(toolbar_widget, test_api_->GetToolbarWidget());
EXPECT_FALSE(toolbar_widget->IsVisible());
EXPECT_FALSE(test_api_->GetMainMenuWidget());
OnOverviewModeEndedWaiter waiter;
ExitOverview();
waiter.Wait();
ASSERT_FALSE(overview_controller->InOverviewSession());
EXPECT_TRUE(game_dashboard_button_widget->IsVisible());
ASSERT_EQ(toolbar_widget, test_api_->GetToolbarWidget());
EXPECT_TRUE(toolbar_widget->IsVisible());
EXPECT_FALSE(test_api_->GetMainMenuWidget());
}
TEST_P(GameTypeGameDashboardContextTest, OverviewModeWithTabletMode) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
const auto* overview_controller = OverviewController::Get();
ASSERT_FALSE(display::Screen::Get()->InTabletMode());
EnterOverview();
ASSERT_TRUE(overview_controller->InOverviewSession());
VerifyFeaturesEnabled(false, false);
ash::TabletModeControllerTestApi().EnterTabletMode();
VerifyFeaturesEnabled(false);
ExitOverview();
ASSERT_FALSE(overview_controller->InOverviewSession());
VerifyFeaturesEnabled(false);
ASSERT_TRUE(display::Screen::Get()->InTabletMode());
EnterOverview();
ASSERT_TRUE(overview_controller->InOverviewSession());
ASSERT_TRUE(display::Screen::Get()->InTabletMode());
VerifyFeaturesEnabled(false);
ExitOverview();
ASSERT_FALSE(overview_controller->InOverviewSession());
VerifyFeaturesEnabled(false);
ash::TabletModeControllerTestApi().LeaveTabletMode();
ASSERT_FALSE(display::Screen::Get()->InTabletMode());
VerifyFeaturesEnabled(true, true);
ash::TabletModeControllerTestApi().EnterTabletMode();
ASSERT_TRUE(display::Screen::Get()->InTabletMode());
EnterOverview();
ASSERT_TRUE(overview_controller->InOverviewSession());
ash::TabletModeControllerTestApi().LeaveTabletMode();
ASSERT_FALSE(display::Screen::Get()->InTabletMode());
ASSERT_TRUE(overview_controller->InOverviewSession());
VerifyFeaturesEnabled(false, false);
ExitOverview();
ASSERT_FALSE(overview_controller->InOverviewSession());
VerifyFeaturesEnabled(true, true);
}
TEST_P(GameTypeGameDashboardContextTest, RecordToggleMainMenuHistogramTest) {
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
const std::string histogram_name_on =
BuildGameDashboardHistogramName(kGameDashboardToggleMainMenuHistogram)
.append(kGameDashboardHistogramSeparator)
.append(kGameDashboardHistogramOn);
const std::string histogram_name_off =
BuildGameDashboardHistogramName(kGameDashboardToggleMainMenuHistogram)
.append(kGameDashboardHistogramSeparator)
.append(kGameDashboardHistogramOff);
test_api_->OpenTheMainMenu();
std::map<GameDashboardMainMenuToggleMethod, int> expected_on_histogram_values;
expected_on_histogram_values
[GameDashboardMainMenuToggleMethod::kGameDashboardButton]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
const int64_t gd_button_toggle_method = static_cast<int64_t>(
GameDashboardMainMenuToggleMethod::kGameDashboardButton);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 1u,
std::vector<int64_t>{1,
gd_button_toggle_method});
test_api_->CloseTheMainMenu();
std::map<GameDashboardMainMenuToggleMethod, int>
expected_off_histogram_values;
expected_off_histogram_values
[GameDashboardMainMenuToggleMethod::kGameDashboardButton]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 2u,
std::vector<int64_t>{0,
gd_button_toggle_method});
auto* event_generator = GetEventGenerator();
event_generator->PressAndReleaseKey(ui::VKEY_G, ui::EF_COMMAND_DOWN);
expected_on_histogram_values
[GameDashboardMainMenuToggleMethod::kSearchPlusG]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 3u,
std::vector<int64_t>{
1,
static_cast<int64_t>(
GameDashboardMainMenuToggleMethod::kSearchPlusG)});
event_generator->PressAndReleaseKey(ui::VKEY_G, ui::EF_COMMAND_DOWN);
expected_off_histogram_values
[GameDashboardMainMenuToggleMethod::kSearchPlusG]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 4u,
std::vector<int64_t>{
0,
static_cast<int64_t>(
GameDashboardMainMenuToggleMethod::kSearchPlusG)});
test_api_->OpenTheMainMenu();
expected_on_histogram_values
[GameDashboardMainMenuToggleMethod::kGameDashboardButton]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 5u,
std::vector<int64_t>{1,
gd_button_toggle_method});
event_generator->PressAndReleaseKey(ui::VKEY_ESCAPE);
base::RunLoop().RunUntilIdle();
expected_off_histogram_values[GameDashboardMainMenuToggleMethod::kEsc]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 6u,
std::vector<int64_t>{0,
static_cast<int64_t>(
GameDashboardMainMenuToggleMethod::kEsc)});
test_api_->OpenTheMainMenu();
expected_on_histogram_values
[GameDashboardMainMenuToggleMethod::kGameDashboardButton]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 7u,
std::vector<int64_t>{1,
gd_button_toggle_method});
LeftClickOn(test_api_->GetMainMenuScreenshotTile());
expected_off_histogram_values
[GameDashboardMainMenuToggleMethod::kActivateNewFeature]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 8u,
std::vector<int64_t>{
0,
static_cast<int64_t>(
GameDashboardMainMenuToggleMethod::kActivateNewFeature)});
test_api_->OpenTheMainMenu();
expected_on_histogram_values
[GameDashboardMainMenuToggleMethod::kGameDashboardButton]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 9u,
std::vector<int64_t>{1,
gd_button_toggle_method});
EnterOverview();
expected_off_histogram_values[GameDashboardMainMenuToggleMethod::kOverview]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 10u,
std::vector<int64_t>{0,
static_cast<int64_t>(
GameDashboardMainMenuToggleMethod::kOverview)});
OnOverviewModeEndedWaiter waiter;
ExitOverview();
waiter.Wait();
test_api_->OpenTheMainMenu();
expected_on_histogram_values
[GameDashboardMainMenuToggleMethod::kGameDashboardButton]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 11u,
std::vector<int64_t>{1,
gd_button_toggle_method});
ash::TabletModeControllerTestApi().EnterTabletMode();
expected_off_histogram_values
[GameDashboardMainMenuToggleMethod::kTabletMode]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
ash::TabletModeControllerTestApi().LeaveTabletMode();
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 12u,
std::vector<int64_t>{
0,
static_cast<int64_t>(
GameDashboardMainMenuToggleMethod::kTabletMode)});
test_api_->OpenTheMainMenu();
expected_on_histogram_values
[GameDashboardMainMenuToggleMethod::kGameDashboardButton]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 13u,
std::vector<int64_t>{1,
gd_button_toggle_method});
const gfx::Point bottom_center =
test_api_->GetMainMenuView()->GetBoundsInScreen().bottom_center();
event_generator->MoveMouseTo(
gfx::Point(bottom_center.x(), bottom_center.y() + 10));
event_generator->ClickLeftButton();
base::RunLoop().RunUntilIdle();
expected_off_histogram_values[GameDashboardMainMenuToggleMethod::kOthers]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 14u,
std::vector<int64_t>{0,
static_cast<int64_t>(
GameDashboardMainMenuToggleMethod::kOthers)});
test_api_->OpenTheMainMenu();
expected_on_histogram_values
[GameDashboardMainMenuToggleMethod::kGameDashboardButton]++;
VerifyHistogramValues(histograms, histogram_name_on,
expected_on_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 15u,
std::vector<int64_t>{1,
gd_button_toggle_method});
CloseGameWindow();
base::RunLoop().RunUntilIdle();
expected_off_histogram_values[GameDashboardMainMenuToggleMethod::kOthers]++;
VerifyHistogramValues(histograms, histogram_name_off,
expected_off_histogram_values);
VerifyToggleMainMenuLastUkmEvent(
ukm_recorder, 16u,
std::vector<int64_t>{0,
static_cast<int64_t>(
GameDashboardMainMenuToggleMethod::kOthers)});
}
TEST_P(GameTypeGameDashboardContextTest,
RecordToolbarToggleStateHistogramTest) {
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
const std::string histogram_name = BuildGameDashboardHistogramName(
kGameDashboardToolbarToggleStateHistogram);
std::map<bool, int> expected_histogram_values;
expected_histogram_values[true]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyToolbarToggleStateLastUkmEvent(ukm_recorder, 1u,
1);
test_api_->CloseTheToolbar();
expected_histogram_values[false]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyToolbarToggleStateLastUkmEvent(ukm_recorder, 2u,
0);
}
TEST_P(GameTypeGameDashboardContextTest,
RecordToolbarClickToExpandStateHistogramTest) {
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
LeftClickOn(test_api_->GetToolbarGamepadButton());
const std::string histogram_name = BuildGameDashboardHistogramName(
kGameDashboardToolbarClickToExpandStateHistogram);
std::map<bool, int> expected_histogram_values;
expected_histogram_values[false]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyToolbarClickToExpandStateLastUkmEvent(
ukm_recorder, 1u, static_cast<int64_t>(false));
LeftClickOn(test_api_->GetToolbarGamepadButton());
expected_histogram_values[true]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyToolbarClickToExpandStateLastUkmEvent(
ukm_recorder, 2u, static_cast<int64_t>(true));
}
TEST_P(GameTypeGameDashboardContextTest,
RecordToolbarNewLocationHistogramTest) {
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
DragToolbarToPoint(
Movement::kMouse,
DragToolbarPointForPosition(GameDashboardToolbarSnapLocation::kTopRight));
const std::string histogram_name = BuildGameDashboardHistogramName(
kGameDashboardToolbarNewLocationHistogram);
std::map<GameDashboardToolbarSnapLocation, int> expected_histogram_values;
expected_histogram_values[GameDashboardToolbarSnapLocation::kTopRight]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyToolbarNewLocationLastUkmEvent(
ukm_recorder, 1u,
static_cast<int64_t>(GameDashboardToolbarSnapLocation::kTopRight));
DragToolbarToPoint(Movement::kMouse,
DragToolbarPointForPosition(
GameDashboardToolbarSnapLocation::kBottomLeft));
expected_histogram_values[GameDashboardToolbarSnapLocation::kBottomLeft]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyToolbarNewLocationLastUkmEvent(
ukm_recorder, 2u,
static_cast<int64_t>(GameDashboardToolbarSnapLocation::kBottomLeft));
DragToolbarToPoint(Movement::kTouch,
DragToolbarPointForPosition(
GameDashboardToolbarSnapLocation::kBottomRight));
expected_histogram_values[GameDashboardToolbarSnapLocation::kBottomRight]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyToolbarNewLocationLastUkmEvent(
ukm_recorder, 3u,
static_cast<int64_t>(GameDashboardToolbarSnapLocation::kBottomRight));
DragToolbarToPoint(
Movement::kTouch,
DragToolbarPointForPosition(GameDashboardToolbarSnapLocation::kTopLeft));
expected_histogram_values[GameDashboardToolbarSnapLocation::kTopLeft]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyToolbarNewLocationLastUkmEvent(
ukm_recorder, 4u,
static_cast<int64_t>(GameDashboardToolbarSnapLocation::kTopLeft));
}
TEST_P(GameTypeGameDashboardContextTest,
RecordRecordingStartSourceHistogramTest) {
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
LeftClickOn(test_api_->GetMainMenuRecordGameTile());
base::RunLoop().RunUntilIdle();
ClickOnStartRecordingButtonInCaptureModeBarView();
const std::string histogram_name = BuildGameDashboardHistogramName(
kGameDashboardRecordingStartSourceHistogram);
std::map<GameDashboardMenu, int> expected_histogram_values;
expected_histogram_values[GameDashboardMenu::kMainMenu]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyRecordingStartSourceLastUkmEvent(
ukm_recorder, 1u,
static_cast<int64_t>(GameDashboardMenu::kMainMenu));
LeftClickOn(test_api_->GetToolbarRecordGameButton());
WaitForCaptureFileToBeSaved();
LeftClickOn(test_api_->GetToolbarRecordGameButton());
ClickOnStartRecordingButtonInCaptureModeBarView();
expected_histogram_values[GameDashboardMenu::kToolbar]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyRecordingStartSourceLastUkmEvent(
ukm_recorder, 2u,
static_cast<int64_t>(GameDashboardMenu::kToolbar));
}
TEST_P(GameTypeGameDashboardContextTest,
RecordScreenshotTakeSourceHistogramTest) {
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuScreenshotTile());
const std::string histogram_name = BuildGameDashboardHistogramName(
kGameDashboardScreenshotTakeSourceHistogram);
std::map<GameDashboardMenu, int> expected_histogram_values;
expected_histogram_values[GameDashboardMenu::kMainMenu]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyScreenshotTakeSourceLastUkmEvent(
ukm_recorder, 1u,
static_cast<int64_t>(GameDashboardMenu::kMainMenu));
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
LeftClickOn(test_api_->GetToolbarScreenshotButton());
expected_histogram_values[GameDashboardMenu::kToolbar]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyScreenshotTakeSourceLastUkmEvent(
ukm_recorder, 2u,
static_cast<int64_t>(GameDashboardMenu::kToolbar));
}
TEST_P(GameTypeGameDashboardContextTest,
RecordGameDashboardFunctionTriggeredHistogramTest) {
if (IsArcGame()) {
game_window_->SetProperty(
kArcGameControlsFlagsKey,
static_cast<ArcGameControlsFlag>(
ArcGameControlsFlag::kKnown | ArcGameControlsFlag::kAvailable |
ArcGameControlsFlag::kEnabled | ArcGameControlsFlag::kHint));
game_window_->SetProperty(kArcResizeLockTypeKey,
ArcResizeLockType::RESIZE_ENABLED_TOGGLABLE);
}
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuFeedbackButton());
const std::string histogram_name =
BuildGameDashboardHistogramName(kGameDashboardFunctionTriggeredHistogram);
std::map<GameDashboardFunction, int> expected_histogram_values;
expected_histogram_values[GameDashboardFunction::kFeedback]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyFunctionTriggeredLastUkmEvent(
ukm_recorder, 1u,
static_cast<int64_t>(GameDashboardFunction::kFeedback));
task_environment()->RunUntilIdle();
LeftClickOn(test_api_->GetMainMenuHelpButton());
expected_histogram_values[GameDashboardFunction::kHelp]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyFunctionTriggeredLastUkmEvent(
ukm_recorder, 2u,
static_cast<int64_t>(GameDashboardFunction::kHelp));
LeftClickOn(test_api_->GetMainMenuSettingsButton());
expected_histogram_values[GameDashboardFunction::kSetting]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyFunctionTriggeredLastUkmEvent(
ukm_recorder, 3u,
static_cast<int64_t>(GameDashboardFunction::kSetting));
LeftClickOn(test_api_->GetSettingsViewBackButton());
expected_histogram_values[GameDashboardFunction::kSettingBack]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyFunctionTriggeredLastUkmEvent(
ukm_recorder, 4u,
static_cast<int64_t>(GameDashboardFunction::kSettingBack));
if (IsArcGame()) {
LeftClickOn(test_api_->GetMainMenuScreenSizeSettingsButton());
base::RunLoop().RunUntilIdle();
expected_histogram_values[GameDashboardFunction::kScreenSize]++;
VerifyHistogramValues(histograms, histogram_name,
expected_histogram_values);
VerifyFunctionTriggeredLastUkmEvent(
ukm_recorder, 5u,
static_cast<int64_t>(GameDashboardFunction::kScreenSize));
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuGameControlsDetailsButton());
expected_histogram_values
[GameDashboardFunction::kGameControlsSetupOrEdit]++;
VerifyHistogramValues(histograms, histogram_name,
expected_histogram_values);
VerifyFunctionTriggeredLastUkmEvent(
ukm_recorder, 6u,
static_cast<int64_t>(GameDashboardFunction::kGameControlsSetupOrEdit));
}
}
TEST_P(GameTypeGameDashboardContextTest,
WelcomeDialogNotificationToggleStateHistogramTest) {
base::HistogramTester histograms;
ukm::TestAutoSetUkmRecorder ukm_recorder;
test_api_->OpenTheMainMenu();
test_api_->OpenMainMenuSettings();
test_api_->ToggleWelcomeDialogSettingsSwitch();
const std::string histogram_name = BuildGameDashboardHistogramName(
kGameDashboardWelcomeDialogNotificationToggleStateHistogram);
std::map<bool, int> expected_histogram_values;
expected_histogram_values[true]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyWelcomeDialogNotificationToggleStateLastUkmEvent(
ukm_recorder, 1u, static_cast<int64_t>(true));
test_api_->ToggleWelcomeDialogSettingsSwitch();
expected_histogram_values[false]++;
VerifyHistogramValues(histograms, histogram_name, expected_histogram_values);
VerifyWelcomeDialogNotificationToggleStateLastUkmEvent(
ukm_recorder, 2u, static_cast<int64_t>(false));
}
INSTANTIATE_TEST_SUITE_P(All,
GameTypeGameDashboardContextTest,
testing::Bool());
class GameDashboardEnabledFeatureTileVerificationTest
: public GameDashboardContextTest,
public testing::WithParamInterface<
std::tuple</*is_arc_game=*/bool,
/*enable_recording_feature=*/bool>> {
public:
GameDashboardEnabledFeatureTileVerificationTest()
: is_arc_game_(std::get<0>(GetParam())),
enable_recording_feature_(std::get<1>(GetParam())) {}
~GameDashboardEnabledFeatureTileVerificationTest() override = default;
void SetUp() override {
GameDashboardContextTest::SetUp();
scoped_feature_list_.InitWithFeatureState(
features::kFeatureManagementGameDashboardRecordGame,
enable_recording_feature_);
CreateGameWindow(is_arc_game_);
}
protected:
const bool is_arc_game_;
const bool enable_recording_feature_;
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_P(GameDashboardEnabledFeatureTileVerificationTest, MainMenuShortcutTiles) {
test_api_->OpenTheMainMenu();
auto* toolbar_tile = test_api_->GetMainMenuToolbarTile();
auto* screenshot_tile = test_api_->GetMainMenuScreenshotTile();
ASSERT_TRUE(toolbar_tile);
ASSERT_TRUE(screenshot_tile);
auto* game_controls_tile = test_api_->GetMainMenuGameControlsTile();
if (is_arc_game_) {
ASSERT_TRUE(game_controls_tile);
ASSERT_EQ(game_controls_tile->tile_type(), FeatureTile::TileType::kCompact);
} else {
ASSERT_FALSE(game_controls_tile);
}
auto* record_game_tile = test_api_->GetMainMenuRecordGameTile();
if (enable_recording_feature_) {
ASSERT_TRUE(record_game_tile);
ASSERT_EQ(record_game_tile->tile_type(), FeatureTile::TileType::kCompact);
} else {
ASSERT_FALSE(test_api_->GetMainMenuRecordGameTile());
}
FeatureTile::TileType expected_tile_type = FeatureTile::TileType::kCompact;
if (!is_arc_game_ && !enable_recording_feature_) {
expected_tile_type = FeatureTile::TileType::kPrimary;
}
ASSERT_EQ(toolbar_tile->tile_type(), expected_tile_type);
ASSERT_EQ(screenshot_tile->tile_type(), expected_tile_type);
}
INSTANTIATE_TEST_SUITE_P(
All,
GameDashboardEnabledFeatureTileVerificationTest,
testing::Combine(testing::Bool(),
testing::Bool()));
class GameDashboardStartAndStopCaptureSessionTest
: public GameDashboardContextTest,
public testing::WithParamInterface<
std::tuple</*is_arc_game_=*/bool,
/*should_start_from_main_menu_=*/bool,
/*should_stop_from_main_menu_=*/bool>> {
public:
GameDashboardStartAndStopCaptureSessionTest()
: is_arc_game_(std::get<0>(GetParam())),
should_start_from_main_menu_(std::get<1>(GetParam())),
should_stop_from_main_menu_(std::get<2>(GetParam())) {}
~GameDashboardStartAndStopCaptureSessionTest() override = default;
void SetUp() override {
GameDashboardContextTest::SetUp();
CreateGameWindow(is_arc_game_);
}
protected:
const bool is_arc_game_;
const bool should_start_from_main_menu_;
const bool should_stop_from_main_menu_;
};
TEST_P(GameDashboardStartAndStopCaptureSessionTest, RecordGameFromMainMenu) {
const auto* capture_mode_controller = CaptureModeController::Get();
const auto& timer = test_api_->GetRecordingTimer();
test_api_->OpenTheMainMenu();
EXPECT_FALSE(capture_mode_controller->is_recording_in_progress());
EXPECT_FALSE(timer.IsRunning());
VerifyGameDashboardButtonState(false);
if (should_start_from_main_menu_) {
const auto* record_game_tile = test_api_->GetMainMenuRecordGameTile();
ASSERT_TRUE(record_game_tile);
LeftClickOn(record_game_tile);
base::RunLoop().RunUntilIdle();
} else {
CHECK(!test_api_->GetToolbarView());
test_api_->OpenTheToolbar();
test_api_->CloseTheMainMenu();
const auto* record_game_button = test_api_->GetToolbarRecordGameButton();
ASSERT_TRUE(record_game_button);
LeftClickOn(record_game_button);
}
ClickOnStartRecordingButtonInCaptureModeBarView();
EXPECT_TRUE(capture_mode_controller->is_recording_in_progress());
EXPECT_TRUE(timer.IsRunning());
VerifyGameDashboardButtonState(true);
if (should_stop_from_main_menu_) {
test_api_->OpenTheMainMenu();
LeftClickOn(test_api_->GetMainMenuRecordGameTile());
} else {
if (should_start_from_main_menu_) {
test_api_->OpenTheMainMenu();
test_api_->OpenTheToolbar();
test_api_->CloseTheMainMenu();
}
CHECK(test_api_->GetToolbarView());
LeftClickOn(test_api_->GetToolbarRecordGameButton());
}
EXPECT_FALSE(capture_mode_controller->is_recording_in_progress());
EXPECT_FALSE(timer.IsRunning());
VerifyGameDashboardButtonState(false);
WaitForCaptureFileToBeSaved();
}
INSTANTIATE_TEST_SUITE_P(
All,
GameDashboardStartAndStopCaptureSessionTest,
testing::Combine(testing::Bool(),
testing::Bool(),
testing::Bool()));
class GameDashboardUIStartupSequenceTest
: public GameDashboardContextTest,
public testing::WithParamInterface<
std::tuple</*show_toolbar=*/bool,
/*show_welcome_dialog=*/bool>> {
public:
GameDashboardUIStartupSequenceTest()
: should_show_toolbar_(std::get<0>(GetParam())),
should_show_welcome_dialog_(std::get<1>(GetParam())) {}
~GameDashboardUIStartupSequenceTest() override = default;
void SetUp() override {
GameDashboardContextTest::SetUp();
game_dashboard_utils::SetShowWelcomeDialog(should_show_welcome_dialog_);
game_dashboard_utils::SetShowToolbar(should_show_toolbar_);
CreateGameWindow(true,
true);
}
void VerifyToolbarVisibility(bool visible) {
if (visible) {
ASSERT_TRUE(test_api_->GetToolbarWidget());
} else {
ASSERT_FALSE(test_api_->GetToolbarWidget());
}
}
void VerifyWelcomeDialogVisibility(bool visible) {
if (visible) {
ASSERT_TRUE(test_api_->GetWelcomeDialogWidget());
} else {
ASSERT_FALSE(test_api_->GetWelcomeDialogWidget());
}
}
protected:
const bool should_show_toolbar_;
const bool should_show_welcome_dialog_;
};
TEST_P(GameDashboardUIStartupSequenceTest, ToolbarAndShowWelcomeDialogStartup) {
if (should_show_welcome_dialog_) {
VerifyWelcomeDialogVisibility(true);
VerifyToolbarVisibility(false);
task_environment()->FastForwardBy(base::Seconds(4));
}
VerifyWelcomeDialogVisibility(false);
VerifyToolbarVisibility(should_show_toolbar_);
}
INSTANTIATE_TEST_SUITE_P(
All,
GameDashboardUIStartupSequenceTest,
testing::Combine(testing::Bool(),
testing::Bool()));
}