Commit 57cc785d authored by Mitsuru Oshima's avatar Mitsuru Oshima Committed by Commit Bot

CrOS: interactive ui test for Overview animations

- This trigger enter/exist with various conditions
number of windows: 2 or 8
tab content: blank or new tab page
device mode: clamshell or tablet mode

This also adds new test api to wait for overview animation state.

Bug: 948324
Change-Id: Ic8d56e12bbd5a60cf93c3add6522cfa128a2764b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1559384
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#649336}
parent dc694293
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
module ash.mojom; module ash.mojom;
enum OverviewAnimationState {
kEnterAnimationComplete,
kExitAnimationComplete,
};
interface ShellTestApi { interface ShellTestApi {
// Returns true if a system modal window is open (e.g. the Wi-Fi network // Returns true if a system modal window is open (e.g. the Wi-Fi network
// password dialog). // password dialog).
...@@ -45,4 +50,7 @@ interface ShellTestApi { ...@@ -45,4 +50,7 @@ interface ShellTestApi {
// Runs the callback when the compositor of the primary display has presented // Runs the callback when the compositor of the primary display has presented
// a frame on screen. // a frame on screen.
WaitForNextFrame() => (); WaitForNextFrame() => ();
// Runs the callback when the overview state becomes |state|.
WaitForOverviewAnimationState(OverviewAnimationState state) => ();
}; };
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include <utility> #include <utility>
#include "ash/accelerators/accelerator_commands.h" #include "ash/accelerators/accelerator_commands.h"
#include "ash/app_list/app_list_controller_impl.h"
#include "ash/app_list/model/app_list_view_state.h"
#include "ash/app_list/views/app_list_view.h"
#include "ash/keyboard/ash_keyboard_controller.h" #include "ash/keyboard/ash_keyboard_controller.h"
#include "ash/root_window_controller.h" #include "ash/root_window_controller.h"
#include "ash/shell.h" #include "ash/shell.h"
...@@ -67,6 +70,41 @@ class PointerMoveLoopWaiter : public ui::CompositorObserver { ...@@ -67,6 +70,41 @@ class PointerMoveLoopWaiter : public ui::CompositorObserver {
DISALLOW_COPY_AND_ASSIGN(PointerMoveLoopWaiter); DISALLOW_COPY_AND_ASSIGN(PointerMoveLoopWaiter);
}; };
// Wait until an overview animation completes. This self destruct
// after executing the callback.
class OverviewAnimationStateWaiter : public OverviewObserver {
public:
OverviewAnimationStateWaiter(
mojom::OverviewAnimationState state,
ShellTestApi::WaitForOverviewAnimationStateCallback callback)
: state_(state), callback_(std::move(callback)) {
Shell::Get()->overview_controller()->AddObserver(this);
}
~OverviewAnimationStateWaiter() override {
Shell::Get()->overview_controller()->RemoveObserver(this);
}
// OverviewObserver:
void OnOverviewModeStartingAnimationComplete(bool canceled) override {
if (state_ == mojom::OverviewAnimationState::kEnterAnimationComplete) {
std::move(callback_).Run();
delete this;
}
}
void OnOverviewModeEndingAnimationComplete(bool canceled) override {
if (state_ == mojom::OverviewAnimationState::kExitAnimationComplete) {
std::move(callback_).Run();
delete this;
}
}
private:
mojom::OverviewAnimationState state_;
ShellTestApi::WaitForOverviewAnimationStateCallback callback_;
DISALLOW_COPY_AND_ASSIGN(OverviewAnimationStateWaiter);
};
} // namespace } // namespace
ShellTestApi::ShellTestApi() : ShellTestApi(Shell::Get()) {} ShellTestApi::ShellTestApi() : ShellTestApi(Shell::Get()) {}
...@@ -202,4 +240,25 @@ void ShellTestApi::WaitForNextFrame(WaitForNextFrameCallback callback) { ...@@ -202,4 +240,25 @@ void ShellTestApi::WaitForNextFrame(WaitForNextFrameCallback callback) {
std::move(callback))); std::move(callback)));
} }
void ShellTestApi::WaitForOverviewAnimationState(
mojom::OverviewAnimationState state,
WaitForOverviewAnimationStateCallback callback) {
auto* overview_controller = Shell::Get()->overview_controller();
if (state == mojom::OverviewAnimationState::kEnterAnimationComplete &&
overview_controller->IsSelecting() &&
!overview_controller->IsInStartAnimation()) {
// If there is no animation applied, call the callback immediately.
std::move(callback).Run();
return;
}
if (state == mojom::OverviewAnimationState::kExitAnimationComplete &&
!overview_controller->IsSelecting() &&
!overview_controller->IsCompletingShutdownAnimations()) {
// If there is no animation applied, call the callback immediately.
std::move(callback).Run();
return;
}
new OverviewAnimationStateWaiter(state, std::move(callback));
}
} // namespace ash } // namespace ash
...@@ -67,6 +67,9 @@ class ShellTestApi : public mojom::ShellTestApi { ...@@ -67,6 +67,9 @@ class ShellTestApi : public mojom::ShellTestApi {
void WaitForNoPointerHoldLock( void WaitForNoPointerHoldLock(
WaitForNoPointerHoldLockCallback callback) override; WaitForNoPointerHoldLockCallback callback) override;
void WaitForNextFrame(WaitForNextFrameCallback callback) override; void WaitForNextFrame(WaitForNextFrameCallback callback) override;
void WaitForOverviewAnimationState(
mojom::OverviewAnimationState state,
WaitForOverviewAnimationStateCallback callback) override;
private: private:
Shell* shell_; // not owned Shell* shell_; // not owned
......
...@@ -34,4 +34,12 @@ void WaitForNoPointerHoldLock(bool wait_for_changes) { ...@@ -34,4 +34,12 @@ void WaitForNoPointerHoldLock(bool wait_for_changes) {
aura::test::WaitForAllChangesToComplete(); aura::test::WaitForAllChangesToComplete();
} }
void WaitForOverviewAnimationState(ash::mojom::OverviewAnimationState state) {
ash::mojom::ShellTestApiPtr shell_test_api = GetShellTestApi();
base::RunLoop run_loop;
shell_test_api->WaitForOverviewAnimationState(state, run_loop.QuitClosure());
run_loop.Run();
}
} // namespace test } // namespace test
...@@ -18,6 +18,9 @@ ash::mojom::ShellTestApiPtr GetShellTestApi(); ...@@ -18,6 +18,9 @@ ash::mojom::ShellTestApiPtr GetShellTestApi();
// aura::test::WaitForAllChangesToComplete(). // aura::test::WaitForAllChangesToComplete().
void WaitForNoPointerHoldLock(bool wait_for_changes = true); void WaitForNoPointerHoldLock(bool wait_for_changes = true);
// Waits until the overview animation finishes and its state becomes |state|.
void WaitForOverviewAnimationState(ash::mojom::OverviewAnimationState state);
} // namespace test } // namespace test
#endif // CHROME_BROWSER_UI_ASH_ASH_TEST_UTIL_H_ #endif // CHROME_BROWSER_UI_ASH_ASH_TEST_UTIL_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/task/post_task.h"
#include "chrome/browser/ui/ash/ash_test_util.h"
#include "chrome/browser/ui/ash/tablet_mode_client_test_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/perf/performance_test.h"
#include "ui/base/test/ui_controls.h"
// Test overview enter/exit animations with following conditions
// int: number of windows : 2, 8
// bool: the tab content (chrome://blank, chrome://newtab)
// bool: tablet mode, if true.
// TODO(oshima): Add Tablet/SplitView mode.
class OverviewAnimationsTest
: public UIPerformanceTest,
public testing::WithParamInterface<::testing::tuple<int, bool, bool>> {
public:
OverviewAnimationsTest() = default;
~OverviewAnimationsTest() override = default;
// UIPerformanceTest:
void SetUpOnMainThread() override {
UIPerformanceTest::SetUpOnMainThread();
int additional_browsers = std::get<0>(GetParam()) - 1;
bool blank_page = std::get<1>(GetParam());
bool tablet_mode = std::get<2>(GetParam());
if (tablet_mode)
test::SetAndWaitForTabletMode(true);
GURL ntp_url("chrome://newtab");
// The default is blank page.
if (blank_page)
ui_test_utils::NavigateToURL(browser(), ntp_url);
for (int i = additional_browsers; i > 0; i--) {
Browser* new_browser = CreateBrowser(browser()->profile());
if (blank_page)
ui_test_utils::NavigateToURL(new_browser, ntp_url);
}
float cost_per_browser = blank_page ? 0.5 : 0.1;
int wait_seconds = (base::SysInfo::IsRunningOnChromeOS() ? 5 : 0) +
additional_browsers * cost_per_browser;
base::RunLoop run_loop;
base::PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
base::TimeDelta::FromSeconds(wait_seconds));
run_loop.Run();
}
// UIPerformanceTest:
std::vector<std::string> GetUMAHistogramNames() const override {
return {
"Ash.Overview.AnimationSmoothness.Enter.ClamshellMode",
"Ash.Overview.AnimationSmoothness.Enter.TabletMode",
"Ash.Overview.AnimationSmoothness.Exit.ClamshellMode",
"Ash.Overview.AnimationSmoothness.Exit.TabletMode",
};
}
private:
DISALLOW_COPY_AND_ASSIGN(OverviewAnimationsTest);
};
IN_PROC_BROWSER_TEST_P(OverviewAnimationsTest, EnterExit) {
// Browser window is used just to identify display.
BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
gfx::NativeWindow browser_window =
browser_view->GetWidget()->GetNativeWindow();
ui_controls::SendKeyPress(browser_window, ui::VKEY_MEDIA_LAUNCH_APP1,
/*control=*/false,
/*shift=*/false,
/*alt=*/false,
/* command = */ false);
test::WaitForOverviewAnimationState(
ash::mojom::OverviewAnimationState::kEnterAnimationComplete);
ui_controls::SendKeyPress(browser_window, ui::VKEY_MEDIA_LAUNCH_APP1,
/*control=*/false,
/*shift=*/false,
/*alt=*/false,
/* command = */ false);
test::WaitForOverviewAnimationState(
ash::mojom::OverviewAnimationState::kExitAnimationComplete);
}
INSTANTIATE_TEST_SUITE_P(,
OverviewAnimationsTest,
::testing::Combine(::testing::Values(2, 8),
/*blank=*/testing::Bool(),
/*tablet=*/testing::Bool()));
...@@ -5225,6 +5225,7 @@ if (!is_android) { ...@@ -5225,6 +5225,7 @@ if (!is_android) {
] ]
sources += [ sources += [
"../browser/ui/ash/drag_to_overview_interactive_uitest.cc", "../browser/ui/ash/drag_to_overview_interactive_uitest.cc",
"../browser/ui/ash/overview_animations_interactive_uitest.cc",
"../browser/ui/ash/split_view_interactive_uitest.cc", "../browser/ui/ash/split_view_interactive_uitest.cc",
] ]
} else { # ! is_chromeos } else { # ! is_chromeos
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment