chromium/ui/views/controls/menu/menu_runner_unittest.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/controls/menu/menu_runner.h"

#include <stdint.h>

#include <memory>
#include <utility>

#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "build/build_config.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/compositor.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/test/event_generator.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_delegate.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_runner_impl.h"
#include "ui/views/controls/menu/menu_types.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/controls/menu/test_menu_item_view.h"
#include "ui/views/test/menu_test_utils.h"
#include "ui/views/test/test_views.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_utils.h"

#if BUILDFLAG(IS_MAC)
#include "ui/views/controls/menu/menu_cocoa_watcher_mac.h"
#endif

namespace views::test {

class MenuRunnerTest : public ViewsTestBase {};

// Tests that MenuRunner is still running after the call to RunMenuAt when
// initialized with , and that MenuDelegate is notified upon
// the closing of the menu.
TEST_F(MenuRunnerTest, AsynchronousRun) {}

// Tests that when a menu is run asynchronously, key events are handled properly
// by testing that Escape key closes the menu.
TEST_F(MenuRunnerTest, AsynchronousKeyEventHandling) {}

// Tests that a key press on a US keyboard layout activates the correct menu
// item.
// This test is flaky on ozone (https://crbug.com/1197217).
#if BUILDFLAG(IS_OZONE)
#define MAYBE_LatinMnemonic
#else
#define MAYBE_LatinMnemonic
#endif
TEST_F(MenuRunnerTest, MAYBE_LatinMnemonic) {}

#if !BUILDFLAG(IS_WIN)
// Tests that a key press on a non-US keyboard layout activates the correct menu
// item. Disabled on Windows because a WM_CHAR event does not activate an item.
TEST_F(MenuRunnerTest, NonLatinMnemonic) {}
#endif  // !BUILDFLAG(IS_WIN)

TEST_F(MenuRunnerTest, MenuItemViewShowsMnemonics) {}

TEST_F(MenuRunnerTest, MenuItemViewDoesNotShowMnemonics) {}

TEST_F(MenuRunnerTest, PrefixSelect) {}

// This test is Mac-specific: Mac is the only platform where VKEY_SPACE
// activates menu items.
#if BUILDFLAG(IS_MAC)
TEST_F(MenuRunnerTest, SpaceActivatesItem) {
  if (!MenuConfig::instance().all_menus_use_prefix_selection)
    return;

  views::test::DisableMenuClosureAnimations();
  InitMenuRunner(0);

  MenuRunner* runner = menu_runner();
  runner->RunMenuAt(owner(), nullptr, gfx::Rect(), MenuAnchorPosition::kTopLeft,
                    ui::MENU_SOURCE_NONE, nullptr);
  EXPECT_TRUE(runner->IsRunning());

  ui::test::EventGenerator generator(GetContext(), owner()->GetNativeWindow());
  generator.PressKey(ui::VKEY_DOWN, 0);
  EXPECT_TRUE(IsItemSelected(1));
  generator.PressKey(ui::VKEY_SPACE, 0);
  views::test::WaitForMenuClosureAnimation();

  EXPECT_FALSE(runner->IsRunning());
  TestMenuDelegate* delegate = menu_delegate();
  EXPECT_EQ(1, delegate->execute_command_id());
  EXPECT_EQ(1, delegate->on_menu_closed_called());
  EXPECT_NE(nullptr, delegate->on_menu_closed_menu());
}
#endif  // BUILDFLAG(IS_MAC)

// Tests that attempting to nest a menu within a drag-and-drop menu does not
// cause a crash. Instead the drag and drop action should be canceled, and the
// new menu should be openned.
TEST_F(MenuRunnerTest, NestingDuringDrag) {}

namespace {

// An EventHandler that launches a menu in response to a mouse press.
class MenuLauncherEventHandler : public ui::EventHandler {};

}  // namespace

// Test harness that includes a parent Widget and View invoking the menu.
class MenuRunnerWidgetTest : public MenuRunnerTest {};

// Tests that when a mouse press launches a menu, that the target widget does
// not take explicit capture, nor closes the menu.
TEST_F(MenuRunnerWidgetTest, WidgetDoesntTakeCapture) {}

// Tests that after showing a menu on mouse press, that the subsequent mouse
// will be delivered to the correct view, and not to the one that showed the
// menu.
//
// The original bug is reproducible only when showing the menu on mouse press,
// as RootView::OnMouseReleased() doesn't have the same behavior.
TEST_F(MenuRunnerWidgetTest, ClearsMouseHandlerOnRun) {}

class MenuRunnerImplTest : public MenuRunnerTest {};

// Tests that when nested menu runners are destroyed out of order, that
// MenuController is not accessed after it has been destroyed. This should not
// crash on ASAN bots.
TEST_F(MenuRunnerImplTest, NestedMenuRunnersDestroyedOutOfOrder) {}

// Tests that when there are two separate MenuControllers, and the active one is
// deleted first, that shutting down the MenuRunner of the original
// MenuController properly closes its controller. This should not crash on ASAN
// bots.
TEST_F(MenuRunnerImplTest, MenuRunnerDestroyedWithNoActiveController) {}

// Test class which overrides the ViewsDelegate. Allowing to simulate shutdown
// during its release.
class MenuRunnerDestructionTest : public MenuRunnerTest {};

base::WeakPtr<internal::MenuRunnerImpl>
MenuRunnerDestructionTest::MenuRunnerAsWeakPtr(
    internal::MenuRunnerImpl* menu_runner) {}

void MenuRunnerDestructionTest::SetUp() {}

// Tests that when ViewsDelegate is released that a nested Cancel of the
// MenuRunner does not occur.
TEST_F(MenuRunnerDestructionTest, MenuRunnerDestroyedDuringReleaseRef) {}

TEST_F(MenuRunnerImplTest, FocusOnMenuClose) {}

TEST_F(MenuRunnerImplTest, FocusOnMenuCloseDeleteAfterRun) {}

// Tests that passing a histogram name to RunMenuAt records a histogram entry.
TEST_F(MenuRunnerTest, ShowMenuHostDurationMetricsDoesLog) {}

// Tests that not passing a histogram name to RunMenuAt does not record a
// histogram entry.
TEST_F(MenuRunnerTest, ShowMenuHostDurationMetricsDoesNotLog) {}

}  // namespace views::test