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 <[email protected]>
Reviewed-by: Xiyuan Xia <[email protected]>
Cr-Commit-Position: refs/heads/master@{#649336}
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc
index 3204e01..177f4eb 100644
--- a/ash/shell_test_api.cc
+++ b/ash/shell_test_api.cc
@@ -8,6 +8,9 @@
 #include <utility>
 
 #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/root_window_controller.h"
 #include "ash/shell.h"
@@ -67,6 +70,41 @@
   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
 
 ShellTestApi::ShellTestApi() : ShellTestApi(Shell::Get()) {}
@@ -202,4 +240,25 @@
           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